SQL Server: разделен низ в оператора SELECT

Искам да разделя датата в колона в 3 полета, използвам тази заявка

SELECT  
SUBSTRING(Account.date, 1, 2) AS "Month",
SUBSTRING(Account.date, 4, 2) AS "Day",
SUBSTRING(Account.date, 7, 4) AS "Year"
FROM Account

Почти всички данни са във формат 02/11/2000, но някои от тях могат да бъдат 02/November/2000 или 2/11/2000.

Единственото обичайно нещо е, че данните са разделени с /. Как мога да отделя тази колона с помощта на разделител?


person user3260664    schedule 28.04.2014    source източник
comment
Как да разберете дали 02/11/2000 е 2 ноември 2000 г. или 11 февруари 2000 г.?   -  person Jeremy Hutchinson    schedule 28.04.2014
comment
Трябва да конвертирате Account.date в datetime и след това да използвате вградената функция Year(), Month, Day, за да получите резултат.   -  person Deepshikha    schedule 28.04.2014
comment
@jrhutch , аз не. Винаги приемам, че последователността е ден/месец/година   -  person user3260664    schedule 28.04.2014
comment
Доста често срещано нещо, с което трябва да се справя, тъй като датите на счетоводния период за нашия софтуер на трета страна се съхраняват като низова стойност (те не могат да бъдат дата, тъй като 13-ият месец е възможен отчетен период – дори и да могат , нямам контрол върху типовете на техните полета). Отговорът на GarethD изглежда най-чистият за моите нужди.   -  person Jon    schedule 12.12.2014


Отговори (6)


Изненадващо CAST('2/November/2000' as datetime) работи (проверено на SQL Server 2008), дава стойност 2000-11-02 00:00:00.000

SELECT  
Month(CAST(Account.date AS DateTime)) "Month",
Day(CAST(Account.date AS DateTime)) "Day",
Year(CAST(Account.date AS DateTime)) "Year",

FROM Account

Но както правилно беше посочено в коментара, как да разберете дали "02/11/2000" е 2 ноември 2000 г. или 11 февруари 2000 г.?

Също така изписването на имената на месеците трябва да е абсолютно правилно, в противен случай преобразуването е неуспешно. Тъй като съхранявате датите като низ, има вероятност да е направен запис като ноември, август и т.н.

Никога не трябва да съхранявате стойностите на датата като низове.

person Mudassir Hasan    schedule 28.04.2014
comment
Работи добре, ако се уверите, че форматът на датата е dmy. Добавете set dateformat dmy; преди заявката, за да сте сигурни. +1. - person Mikael Eriksson; 28.04.2014
comment
да, @MikaelEriksson .. без да правите set dateformat, стойност като 17/01/2000 ще изведе грешка при преобразуването е неуспешно.. благодаря за посочването - person Mudassir Hasan; 28.04.2014
comment
Отличен отговор, добре обяснено. - person Alec.; 28.04.2014

Можете да го направите по този начин, като използвате функциите CHARINDEX и SUBSTRING

select 
    LEFT(Account.date, CHARINDEX('/', Account.date) - 1),
    SUBSTRING(Account.date, CHARINDEX('/', Account.date) + 1, LEN(Account.date) - CHARINDEX('/', Account.date) - CHARINDEX('/', Account.date, CHARINDEX('/', Account.date)) - 2),
    REVERSE(LEFT(REVERSE(Account.date), CHARINDEX('/', REVERSE(Account.date)) - 1))
FROM Account
person Szymon    schedule 28.04.2014
comment
RIGHT(Account.date, CHARINDEX('/', REVERSE(Account.date)) - 1) . . . За третата част. Страхотен отговор, използвах този стил само с тази малка промяна - person Suamere; 04.04.2017

Можете леко да злоупотребите с функцията PARSENAME тук:

SELECT  FirstPart = PARSENAME(REPLACE(Account.Date, '/', '.'), 3),
        SecondPart = PARSENAME(REPLACE(Account.Date, '/', '.'), 2),
        ThirdPart = PARSENAME(REPLACE(Account.Date, '/', '.'), 1)
FROM    (VALUES
            ('02/November/2000'),
            ('2/11/2000')
        ) Account (Date);

Ще даде:

FirstPart   SecondPart  ThirdPart
02          November    2000
2           11          2000

Бих обаче силно препоръчал съхраняване на вашите дати с помощта на подходящия тип данни!. SQL Server 2012 има функцията TRY_CONVERT, която може да улесни такива преобразувания, но все пак трябва да знаете в какъв формат е датата на вашия низ, 2/11/2000 може да бъде 2 ноември или 11 февруари в зависимост от вашите регионални настройки.

person GarethD    schedule 28.04.2014

Можете да използвате комбинацията от функция CharIndex и Substring в SQL, за да разделите низа въз основа на разделител.

Можете да проверите примери за CharIndex тук SQL Server 2005 Използване на CHARINDEX() за разделяне на низ и тук SQL Server - намерете n-то срещане в низ

person Nickolay Komar    schedule 28.04.2014

Ако приемем, че колоната account.date на вашата база данни съдържа валидна datetime или date стойност, трябва да използвате функции за дата на SQLServers като:

select month(getDate()) as "Month", 
       day(getDate()) as "Day", 
       year(getDate()) as "Year"

Замених вашата колона account.date с getDate(), за да има някои тестови стойности. Това се преобразува във вашия SQL по следния начин

SELECT  
month(Account.date) AS "Month",
day(Account.date) AS "Day",
year(Account.date) AS "Year"
FROM Account

Съхраняването на тези стойности на дата като varchar би било IMHO недостатък на дизайна на вашата структура на базата данни. Датите се форматират по различни начини за текст. Това е представянето на данните от вашата база данни. За да обработите вашите данни, винаги ще обработвате предварително вашите текстови дати. Това е лоша практика.

Ако наистина имате стойности на varchar, има няколко SO въпроса като: Как да разделя низ, за ​​да имам достъп до елемент x?.

person wumpz    schedule 28.04.2014

Опитайте тази:

DECLARE @VALUE VARCHAR(100)<BR>
SET @VALUE ='2/11/2000' <BR>
SELECT SUBSTRING(@VALUE,0,CHARINDEX('/',@VALUE,0)),

SUBSTRING(@VALUE,
CHARINDEX('/',@VALUE,0)+1,

(CHARINDEX('/',@VALUE,(CHARINDEX('/',@VALUE,0)+1)) - 
CHARINDEX('/',@VALUE,0) - 1)

),RIGHT(@VALUE,4)
person Community    schedule 28.04.2014