How do I change text data to numeric in SQL Server? - sql-server

SELECT
a.AccountNumber, a.FirstName, a.LastName, a.Address, a.City, a.State,
a.Zip, a.EmailAddress, a.PhoneNumber, a.LastUpdated, a.LastVisit,
a.TotalSales, a.AccountOpened, a.CustomText4 as StoreCode,
CASE
WHEN (a.CustomText1 IS 'JAN') THEN '1'
END AS DOB,
GETDATE() as Extract_date
FROM
database.dbo.Customer a
CustomText1 column has Month data with a text data.I am trying to convert JAN-DEC to Numeric.
CASE WHEN IS '' isn't working.

"IS" is not a valid expression for CASE statement. Check the online doc, you have a couple ways to do it, this is the simplest way, repeat for the rest of the months.
SELECT DOB =
CASE a.CustomText1
WHEN 'JAN' THEN '1'
WHEN 'FEB' THEN '2'
WHEN 'MAR' THEN '3'
ELSE a.CustomText1
END
FROM database.dbo.Customer a

Greg's answer works, but it's over 12 lines. Here's how to do it in one.
SELECT MONTH(CAST('01' + CustomText1 + '00' AS DATE))
FROM dbo.Customer

Related

SQL Error "Conversion failed when converting date and/or time from character string" whereas not converting

With the following query (which contains no string to date and/or time conversion):
SELECT
Date,
RangeFam,
QTY,
Country
FROM (
SELECT Q_QTM as Qty,
Q_OFDFIN as Date,
Q_PAYS as Country,
CASE Q_DTRI05
WHEN 'eBALTIC - EBB' THEN 'EBAB'
WHEN 'Baltic -' THEN 'BALT'
WHEN 'eBALTIC - EBF' THEN 'EBAF'
WHEN 'Roof-tops - ENERGY' THEN 'ENER'
WHEN 'Roof-tops - FLEXAIR' THEN 'FLER'
END as RangeFam
FROM [sales].[dbo].[CARNET2_D]
WHERE Q_OFET='D'
and Q_TYPE='M'
UNION ALL
SELECT Qty,
Range_Code as RangeFam,
ShippingDate as Date,
CASE Country collate DATABASE_DEFAULT
WHEN 'France' THEN 'FRANCE'
WHEN 'Netherlands' THEN 'PAYS BAS'
WHEN 'Belgium' THEN 'BELGIQUE'
WHEN 'Portugal' THEN 'PORTUGAL'
WHEN 'Spain' THEN 'ESPAGNE'
END AS Country
FROM [crmv2].[dbo].[View_Forecastdata_Extended]
WHERE BaseUnit='1'
and (Project_status='Detection / Faisability' or Project_status='Execution' or Project_status='Quotation' or Project_status='Specification stage')
and [Report_S3A/B_group]='Rooftop'
and Sop='1'
and SopValid='1'
and (Sourcing='L&B' or Sourcing='LON' or Sourcing='BUR')
) as T1
ORDER BY Date
I get this error:
Msg 241, Level 16, State 1, Line 1
Conversion failed when converting date and/or time from character string.
Something weird is that if I remove all the code related to the field RangeFam the query is ok so I guess I miss something about it
Thank you
When I say that when I remove the code about RangeFam I mean that there is no problem with the following Query:
SELECT
Date,
--RangeFam,
QTY,
Country
FROM (
SELECT Q_QTM as Qty,
Q_OFDFIN as Date,
Q_PAYS as Country
--CASE Q_DTRI05
-- WHEN 'eBALTIC - EBB' THEN 'EBAB'
-- WHEN 'Baltic -' THEN 'BALT'
-- WHEN 'eBALTIC - EBF' THEN 'EBAF'
-- WHEN 'Roof-tops - ENERGY' THEN 'ENER'
-- WHEN 'Roof-tops - FLEXAIR' THEN 'FLER'
--END as RangeFam
FROM [sales].[dbo].[CARNET2_D]
WHERE Q_OFET='D'
and Q_TYPE='M'
UNION ALL
SELECT Qty,
--Range_Code as RangeFam,
ShippingDate as Date,
CASE Country collate DATABASE_DEFAULT
WHEN 'France' THEN 'FRANCE'
WHEN 'Netherlands' THEN 'PAYS BAS'
WHEN 'Belgium' THEN 'BELGIQUE'
WHEN 'Portugal' THEN 'PORTUGAL'
WHEN 'Spain' THEN 'ESPAGNE'
END AS Country
FROM [crmv2].[dbo].[View_Forecastdata_Extended]
WHERE BaseUnit='1'
and (Project_status='Detection / Faisability' or Project_status='Execution' or Project_status='Quotation' or Project_status='Specification stage')
and [Report_S3A/B_group]='Rooftop'
and Sop='1'
and SopValid='1'
and (Sourcing='L&B' or Sourcing='LON' or Sourcing='BUR')
) as T1
ORDER BY Date
The way the query is written the contents of Q_OFDFIN in the first subquery are UNIONed with the contents of Range_Code in the second one. Since one seems to be a Date and the other a string, the server has to convert them to a common type.
UNION and UNION ALL work on result fields by position, not subquery aliases.
To fix the problem ensure the columns appear in the correct order:
FROM (
SELECT Q_QTM as Qty,
Q_OFDFIN as Date,
Q_PAYS as Country,
CASE Q_DTRI05
WHEN 'eBALTIC - EBB' THEN 'EBAB'
WHEN 'Baltic -' THEN 'BALT'
WHEN 'eBALTIC - EBF' THEN 'EBAF'
WHEN 'Roof-tops - ENERGY' THEN 'ENER'
WHEN 'Roof-tops - FLEXAIR' THEN 'FLER'
END as RangeFam
FROM [sales].[dbo].[CARNET2_D]
WHERE Q_OFET='D'
and Q_TYPE='M'
UNION ALL
SELECT Qty,
ShippingDate as Date,
CASE Country collate DATABASE_DEFAULT
WHEN 'France' THEN 'FRANCE'
WHEN 'Netherlands' THEN 'PAYS BAS'
WHEN 'Belgium' THEN 'BELGIQUE'
WHEN 'Portugal' THEN 'PORTUGAL'
WHEN 'Spain' THEN 'ESPAGNE'
END AS Country,
Range_Code as RangeFam
FROM [crmv2].[dbo].[View_Forecastdata_Extended]
...

How to get minimum value with added string in SQL Server?

I have a table with 3 fields: Item Number, Promised Date and Promised Ship Date.
I wanted to get pull the columns Item Number with the earliest promised date so my query is
SELECT
ITEMNMBR,
MIN(PRMDATE) AS [Earliest Promised Date]
FROM
Table1
GROUP BY
ITEMNMBR
This works fine but I wanted to add a string with that [Earliest Promised Date]: Confirmed or Unconfirmed. It is determined by Promised Ship Date. If the promised ship date is equal to the promised date, it is unconfirmed and if they are unequal then it is confirmed.
I have tried but does not work:
SELECT
ITEMNMBR,
MIN(CASE
WHEN PRMDATE = PRMSHPDTE
THEN CONVERT(varchar, PRMDATE, 101) + ' - Unconfirmed'
WHEN PRMDATE <> PRMSHPDTE
THEN CONVERT(varchar, PRMDATE, 101) + ' - Confirmed'
ELSE 'Error'
END) AS [Promised Date]
FROM
Table1
GROUP BY
ITEMNMBR
Can you point out what I have done wrong in the second query?
I believe the problem is rooted in the use of format 101 and alphabetical sorting. You might need to expound on the "(un)confirmed" logic but something like this should get you in the right direction.
SELECT
ITEMNMBR,
CONVERT(VARCHAR(12), MIN(PRMDATE), 101) + ' - ' +
MAX(CASE
WHEN PRMDATE = PRMSHPDTE THEN 'Unconfirmed'
WHEN PRMDATE <> PRMSHPDTE THEN 'Confirmed'
ELSE 'XX Error'
END) AS [Promised Date]
FROM
Table1
GROUP BY
ITEMNMBR;

PIVOT table is converting all columns to DATE

Why does my view get created with FIRM_PANEL and FIRM_DATE as DATEs and not an NVARCHAR and a DATE as I expect?
SELECT DISTINCT piv3.CASE_NUMBER, FIRM_PANEL, FIRM_DATE
FROM
(
SELECT DISTINCT piv2.CASE_NUMBER, piv2.DETAIL_CODE,
CASE piv2.DATA_FLAGS
WHEN 'TEXT_FLAG' THEN CONVERT(NVARCHAR, TEXT_VALUE)
WHEN 'DATE_FLAG' THEN CONVERT(DATE, DATE_VALUE)
END AS 'VALUE'
FROM
(
SELECT DISTINCT CASE_NUMBER, DETAIL_CODE, piv.DATA_FLAGS, TEXT_VALUE, CONVERT(DATE, DATE_VALUE) AS DATE_VALUE
FROM table
UNPIVOT
(
YES_OR_NO
FOR DATA_FLAGS IN (DATE_FLAG, TEXT_FLAG)
) piv
) piv2
) as sourcetable
PIVOT
(
MAX(VALUE)
FOR DETAIL_CODE IN (FIRM_PANEL,
FIRM_DATE )
) AS piv3
Let me explain each nested pivot/select. The first SELECT gives you an idea how the data is store raw. I needed a way to show 1 CASE_NUMBER and DETAIL_CODEs as unique columns.
SELECT DISTINCT CASE_NUMBER, DETAIL_CODE, piv.DATA_FLAGS, TEXT_VALUE,
CONVERT(DATE, DATE_VALUE) AS DATE_VALUE
FROM table
I then needed to take DATE_VALUE and TEXT_VALUE and merge into one column called VALUE, hence my UNPIVOT.
SELECT DISTINCT piv2.CASE_NUMBER, piv2.DETAIL_CODE,
CASE piv2.DATA_FLAGS
WHEN 'TEXT_FLAG' THEN CONVERT(NVARCHAR, TEXT_VALUE)
WHEN 'DATE_FLAG' THEN CONVERT(NVARCHAR, DATE_VALUE)
END AS 'VALUE'
FROM
(
SELECT DISTINCT CASE_NUMBER, DETAIL_CODE, piv.DATA_FLAGS, TEXT_VALUE, CONVERT(DATE, DATE_VALUE) AS DATE_VALUE
FROM table
UNPIVOT
(
YES_OR_NO
FOR DATA_FLAGS IN (DATE_FLAG, TEXT_FLAG)
) piv
) piv2
Then my final SQL (top) finally PIVOTs again and removes nulls and interprets if the column was a text field then use NVARCHAR and if date use DATE.
However the only way I can SELECT from the view without errors is making both NVARCHAR or else I'll receive "Conversion failed when converting date and/or time from character string" due to both columns being a DATE field when they shouldn't be. However I do not understand why the view is created with the two DATE columns. My current workaround is setting as string and just doing the conversion when selecting from the view.
Sorry for the wordiness.
I think an-d was on the right path.. You should definitely try case aggregates.
SELECT CASE_NUMBER,
MAX( CASE WHEN DETAIL_CODE = 'FIRM_PANEL' THEN TEXT_VALUE END) AS FIRM_PANEL,
MAX( CASE WHEN DETAIL_CODE = 'FIRM_DATE' THEN CONVERT(DATE, DATE_VALUE) END) AS FIRM_DATE
FROM table
GROUP BY CASE_NUMBER
You can add more where clauses to the case expression if you need to, but the above may work.
I don't quite understand the reasons for your use of pivots, but the problem seems to be that you're trying to cast the same column VALUE as both DATE and NVARCHAR here -
...
CASE piv2.DATA_FLAGS
WHEN 'TEXT_FLAG' THEN CONVERT(NVARCHAR, TEXT_VALUE)
WHEN 'DATE_FLAG' THEN CONVERT(DATE, DATE_VALUE)
END AS 'VALUE'
...
You can't control when SQL Server performs the CONVERT operation and it might do it before checking the DATA_FLAGS. Your query should work if you try to move the CONVERT outside to the first select -
SELECT DISTINCT piv3.CASE_NUMBER, CONVERT(NVARCHAR, FIRM_PANEL), CONVERT(DATE, FIRM_DATE)
FROM
(
SELECT DISTINCT piv2.CASE_NUMBER, piv2.DETAIL_CODE,
CASE piv2.DATA_FLAGS
WHEN 'TEXT_FLAG' THEN TEXT_VALUE
WHEN 'DATE_FLAG' THEN DATE_VALUE
END AS 'VALUE'
...
If you're open to not using pivots, here's a simple alternative to get the same result -
SELECT CASE_NUMBER
, MAX(CASE WHEN DATA_FLAGS = 'TEXT_FLAG' THEN TEXT_VALUE END) FIRM_DATE
, MAX(CASE WHEN DATA_FLAGS = 'DATE_FLAG' THEN CONVERT(DATE, DATE_VALUE) END) FIRM_PANEL
FROM #in
GROUP BY CASE_NUMBER
This gives the same result as you're looking for with the columns in their expected data types. Note that it assumes you will have only one record with TEXT_FLAG and DATE_FLAG each for every CASE_NUMBER.

SQL Server : use LIKE inside a CASE statement to replace characters in string

Apologies for poorly worded question.
I have the following column description with contents like:
2511420s5
38114CR
2510014IND
I want to get rid of the s5,CRand INDusing a CASE statement.
Something like:
select
CASE
WHEN description LIKE ('%CRT%', '%IND%', '%MR%') THEN ''
ELSE description
END as test
from table
So to summarize, I want to strip the S5 from my string if it exists.
I have a list of about 15 possibilities so don't want to use a nested replace statement.
Can this be done with CASE or is there a better option?
Thanks,
Assuming there is no better rule; i.e. the text is not always at the end of the string, you could store the ignore tokens in a table, join and examine;
;with ignore(token) as ( --a real table is better
select 's5' union
select 'ind' union
select 'cr'
)
select distinct
id, -- need > 1 col
case when ignore.token is null then description else '' end
from table
left join ignore on description like '%' + token + '%'
This is the correct query:
;with ignore(token) as (
select 's5' union
select 'ind' union
select 'cr'
)
select distinct
id, -- need > 1 col
case when ignore.token is null then description
else REPLACE(description, ignore.token, '')
end
from table_1
left join ignore on description like '%' + token + '%';

Order by more than clause in a case statement

I'm working a query that will retrieve various personal information, including first and last names. I want to change the order that the data is returned by based on a passed parameter, called #p_Code. When #p_Code is 4, I want to order by first name, then last name. If it's not 4, then I want to order by last name, then first name.
I'm working with MS Sql.
Here's the query as it stands:
Select Last,
First,
Phone,
Email
From Master.dbo.Cust
Order by
case #p_Code
when '4' then
([First], [Last])
else
([Last], [First])
end
This should do it:
DECLARE #p_Code VARCHAR(10)
SET #p_Code = '4'
Select [Last],
[First],
Phone,
Email
From Master.dbo.Cust
Order by
case WHEN #p_Code = '4' THEN (RANK() OVER (ORDER BY [First], [Last]))
ELSE (RANK() OVER (ORDER BY [Last],[First] )) END
I don't have a test environment handy, but how about this:
Select Last,
First,
Phone,
Email,
(case #p_Code when '4' then [first] else [last] end) as key1,
(case #p_Code when '4' then [last] else [first] end) as key2
From Master.dbo.Cust
Order by key1, key2

Resources