I Have a table like below,
client id order q order date
----------- ----------- ----------
1 0 2016-02-01
1 0 2016-05-03
When the sum([order q]) = 0 I want the result is '-', If it returns value greater than zero,I Want the result.
I tried the following query, but it returns zero only.
select case when sum([order q]) = 0 THEN '-' else sum([order q]) END
from t1
Help me to fix this.
I believe that you are intending to GROUP BY the client id value:
SELECT CASE WHEN SUM([order q]) = 0 THEN '-'
ELSE CAST(SUM([order q]) AS VARCHAR)
END
FROM t1
GROUP BY [client id]
You should convert the sum() to Varchar. Try like this,
DECLARE #T TABLE (
clientid INT
,orderq INT
,orderdate DATE
)
INSERT INTO #T
VALUES (
1
,0
,'2016-02-01'
)
,(
1
,0
,'2016-05-03'
)
SELECT CASE
WHEN sum(orderq) > 0
THEN convert(VARCHAR(10), sum(orderq))
ELSE '-'
END as orderq
FROM #t
Since '-' is a character and sum([order q]) will be of numeric data type you cannot use the syntax as you mentioned in the question, you have to convert both into similar data types. Try this query
SELECT CASE ISNULL(SUM([order q]), 0)
WHEN 0
THEN CONVERT( CHAR(1), '-')
ELSE CONVERT(VARCHAR(20), SUM([order q]))
END
FROM t1;
As your datatype for order column is int so it won't work . The datatype is always set to a column datatype which you are using in aggregate function. As you are mentioning here '-' it internally converts it in to -0 and as 0 cant be in negative it displays you 0
;WITH CTE
AS (
SELECT CONVERT(VARCHAR(10),SUM([order q])) as c1 from t
)
SELECT
CASE c1
WHEN '0' THEN '-'
ELSE c1
END as c2
from CTE
Related
The field has a date value in this format : 20230215 : YYYYMMDD
I want to select only those records where date is a date in last 7 days.
Is there a way to achieve this in Snowflake with date format?
WITH
CTE
AS
(
SELECT
CASE
WHEN (DATECOL = '' AND DATECOL is NULL and DATECOL = 'NULL') THEN '3000-01-01'
ELSE TO_CHAR(TO_DATE(TO_CHAR(DATECOL), 'YYYYMMDD'), 'YYYY-MM-DD')
END AS DATECOL_FINAL
FROM TABLE
)
SELECT * FROM CTE WHERE DATECOL_FINAL > current_date () - 7
This code does not work, error : Can't parse ' ' as date with format 'YYYYMMDD'
The DATECOL is varchar (8)
I think you want. I'll leave it up to you to decide on > vs >=
try_to_date(col) > current_date()-7
If you want to include empty strings and literal nulls, modify that to
try_to_date(col) > current_date()-7 or try_to_date(col) is null
Below code solved the issue in Snowflake
WITH
CTE_DATE
AS
(
SELECT
CASE
WHEN (DATECOL <> '' AND DATECOL is NOT NULL and DATECOL <> 'NULL') THEN TO_CHAR(TO_DATE(TO_CHAR(DATECOL), 'YYYYMMDD'), 'YYYY-MM-DD')
ELSE '3000-01-01'
END AS TEST_DATE,*
FROM TABLENAME WHERE LEN (DATECOL) <> 1
)
SELECT * FROM CTE_DATE WHERE TEST_DATE > CURRENT_DATE()-7 ORDER BY TEST_DATE ASC
I have a table in SQL Server:
CREATE TABLE healthRegistration
(
ID uniqueidentifier PRIMARY KEY,
RegisterDateTime DateTime NOT NULL,
RUFeelingWell Bool NOT NULL
);
The RegisterDateTime is the date and time that the user created the register and RUFeelingWell is a boolean value.
I want to create a query that returns 3 columns: Register Date, Count of entries with RUFeelingWell = False on that date, Count of entries with RUFeelingWell = True on that date
How can I do this?
SELECT CAST(T.RegisterDateTime AS DATE)REGISTERDATE,
SUM
(
CASE
WHEN T.RUFeelingWell =1 THEN 1
ELSE 0
END
)AS TRUE_RECORDS,
SUM
( CASE
WHEN T.RUFeelingWell =0 THEN 1
ELSE 0
END
)AS FALSE_RECORDS
FROM healthRegistration AS T
GROUP BY CAST(T.RegisterDateTime AS DATE)
Try this query:
Select
Convert(char(8), RegisterDateTime, 112),
Sum(Case RUFeelingWell When 1 Then 1 Else 0 End) As wellnos,
Sum(Case RUFeelingWell When 0 Then 1 Else 0 End) As notwellnos
From healthRegistration
Group By Convert(char(8), RegisterDateTime, 112)
Order By Convert(char(8), RegisterDateTime, 112)
Here Convert(char(8), RegisterDateTime, 112) gives date in YYYYMMDD format so that entries for a day are summed together.
Boolean values are stored as 1 and 0 in the database
Following is my table (TestTable) where Column_3 is NULL.
Column_1 Column_2 Column_3
-------- -------- --------
1 2 NULL
1 3 NULL
5 6 NULL
As per functionality, user can select one or more columns.
For example, if user selects Column_3 & Column_2 where Column_3 is NULL. I want to tell user that Column_3 is NULL.
Query : Works for single column
if exists(select * from TestTable where Column_3 is null)
print 'Yes'
else
print 'No'
Result :
Yes
Query : For multiple Columns (not working)
declare #columns nvarchar(max), #tableName nvarchar(max), #query nvarchar(max)
set #columns = 'Column_3, Column_2'
set #tableName = 'TestTable'
set #query = 'select * from (select ' + #columns + ' from ' + #tableName + ') as Result'
print #query
EXEC SP_EXECUTESQL #query
Here
#query = select * from (select Column_3, Column_2 from TestTable) as Result
Above query gives me result for those two columns. I'm not sure how can I check NULL in this query for multiple columns. If I add IS NULL (like I did for single column) after or before last parenthesis it gives me Incorrect syntax near the keyword 'is'. error. How can I achieve my goal in this situation?
Two Solutions (Column is All NULLs, Column Contains Some NULLs)
I have slightly altered your original example in order to provide two solutions:
Column_1 Column_2 Column_3
-------- -------- --------
1 2 NULL
1 NULL NULL
5 6 NULL
First, test for NULLs and count them:
select
sum(case when Column_1 is null then 1 else 0 end) as Column_1,
sum(case when Column_2 is null then 1 else 0 end) as Column_2,
sum(case when Column_3 is null then 1 else 0 end) as Column_3,
from TestTable
Yields a count of NULLs:
Column_1 Column_2 Column_3
0 1 3
Where the result is 0, there are no NULLs.
Second, let's count the non-NULLs:
select
sum(case when Column_1 is null then 0 else 1 end) as Column_1,
sum(case when Column_2 is null then 0 else 1 end) as Column_2,
sum(case when Column_3 is null then 0 else 1 end) as Column_3,
from TestTable
...But because we're counting non-NULLs here, this can be simplified to:
select
count(Column_1) as Column_1,
count(Column_2) as Column_2,
count(Column_3) as Column_3,
from TestTable
Either one yields:
Column_1 Column_2 Column_3
3 2 0
Where the result is 0, the column is entirely made up of NULLs.
If you only need to check a given column, then TOP 1 is quicker because it should stop at the first hit:
select count(*) from (select top 1 'There is at least one NULL' AS note from TestTable where Column_3 is NULL) a
0 = There are no NULLs, 1 = There is at least one NULL
SELECT COUNT(*) FROM (SELECT TOP 1 'There is at least one non-NULL' AS note FROM sat_data_active_season_group WHERE season_group IS NOT NULL) a
0 = They are all NULL, 1 = There is at least one non-NULL
I hope this helps.
we can check with the help of IN like
...WHERE NULL IN (Column_2, Column_3)
from your comment Well the multiple column will be Column_3, Column_2 in format
might be this is helpful for you
select * from (select Column_3, Column_2 from #temp where null in (Column_3, Column_2)) as Result
Try as below.
You can find the null able column by using CASE.
Select CASE WHEN Column_3 IS NULL THEN 'Column 3 is null' ELSE Column_3 END as Column3,
CASE WHEN Column_2 IS NULL THEN 'Column 2 is null' ELSE Column_2 END as Column2
From TableName
It sounds like you need a CASE statement. Reference
Example:
SELECT CASE
WHEN ISNULL(Column_3) THEN -- do something
WHEN NOT ISNULL(Column_3) THEN -- do something else
AS Column_3 -- or some other name
I am currently working on a query that needs to calculate the difference in days between two different dates. I've had issues with our DATE columns before, because they are all being stored as numeric columns which is a complete pain.
I tried using CONVERT as I had done in the past to try and get the different pieces of the DATETIME string built, but I am not having any luck.
The commented line --convert(datetime,) is where I am having the issue. Basically, I need to convert PO_DATE and LINE_DOCK_DATE to a format that is usable, so I can calculate the difference between the two in days.
USE BWDW
GO
SELECT
[ITEM_NO]
,[ITEM_DESC]
,[HEADER_DUE_DATE]
,[BWDW].[dbo].[DS_tblDimWhs].WHS_SHORT_NAME AS 'Warehouse'
,[BWDW].[dbo].[DS_tblFactPODtl].[PO_NO] AS 'PO NUMBER'
,[BWDW].[dbo].[DS_tblFactPODtl].[PO_DATE] AS 'Start'
,[BWDW].[dbo].[DS_tblFactPODtl].[PO_STATUS] AS 'Status'
,[BWDW].[dbo].[DS_tblFactPODtl].[LINE_DOCK_DATE] AS 'End'
--,(SELECT CONVERT(DATETIME, CONVERT(CHAR(8), [BWDW].[dbo].[DS_tblFactPODtl].[PO_DATE])) FROM dbo.DS_tblFactPODtl)
FROM [BWDW].[dbo].[DS_tblFactPODtl]
INNER JOIN [BWDW].[dbo].[DS_tblDimWhs] ON [BWDW].[dbo].[DS_tblFactPODtl].WAREHOUSE = [BWDW].[dbo].[DS_tblDimWhs].WAREHOUSE
INNER JOIN [BWDW].[dbo].[DS_tblFactPO] ON [BWDW].[dbo].[DS_tblFactPODtl].PO_NO = [BWDW]. [dbo].[DS_tblFactPO].PO_NO
WHERE [BWDW].[dbo].[DS_tblFactPODtl].[PO_STATUS] = 'Closed'
AND [BWDW].[dbo].[DS_tblFactPODtl].[LINE_DOCK_DATE] <> 0
I have a snippet I saved from a previous project I worked on that needed to only display results from today through another year. That had a bunch of CAST and CONVERTS in it, but I tried the same methodology with no success.
In the long run, I want to add a column to each database table to contain a proper datetime column that is usable in the future... but that is another story. I have read numerous posts on stackoverflow that talk about converting to NUMERIC and such, but nothing out of a NUMERIC back to DATETIME.
Example data:
Start | End | Difference
--------------------------------
20110501 | 20111019 | 171
20120109 | 20120116 | 7
20120404 | 20120911 | 160
Just trying to calculate the difference..
MODIFIED PER AARON:
SELECT
FPODtl.[ITEM_NO] AS [Item]
,FPODtl.[ITEM_DESC] AS [Description]
,D.WHS_SHORT_NAME AS [Warehouse]
,FPODtl.[PO_NO] AS [PO NUMBER]
,FPODtl.[PO_DATE] AS [Start]
,FPODtl.[PO_STATUS] AS [Status]
,FPODtl.[LINE_DOCK_DATE] AS [End]
,DATEDIFF
(
DAY,
CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.PO_DATE)) = 1
THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.PO_DATE)) END,
CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) = 1
THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) END
)
FROM [dbo].[DS_tblFactPODtl] AS FPODtl
INNER JOIN [dbo].[DS_tblDimWhs] AS D
ON FPODtl.WAREHOUSE = D.WAREHOUSE
INNER JOIN [dbo].[DS_tblFactPO] AS FPO
ON FPODtl.PO_NO = FPO.PO_NO
WHERE FPODtl.[PO_STATUS] = 'Closed'
AND FPODtl.[LINE_DOCK_DATE] <> 0;
DECLARE #x NUMERIC(10,0);
SET #x = 20110501;
SELECT CONVERT(DATETIME, CONVERT(CHAR(8), #x));
Result:
2011-05-01 00:00:00.000
To compare two:
DECLARE #x NUMERIC(10,0), #y NUMERIC(10,0);
SELECT #x = 20110501, #y = 20111019;
SELECT DATEDIFF
(
DAY,
CONVERT(DATETIME, CONVERT(CHAR(8), #x)),
CONVERT(DATETIME, CONVERT(CHAR(8), #y))
);
Result:
171
More importantly, fix the table. Stop storing dates as numbers. Store them as dates. If you get errors with this conversion, it's because your poor data choice has allowed bad data into the table. You can get around that - potentially - by writing the old version of TRY_CONVERT():
SELECT DATEDIFF
(
DAY,
CASE WHEN ISDATE(col1)=1 THEN CONVERT(DATETIME, col1) END,
CASE WHEN ISDATE(col2)=1 THEN CONVERT(DATETIME, col2) END
)
FROM
(
SELECT
col1 = CONVERT(CHAR(8), col1),
col2 = CONVERT(CHAR(8), col2)
FROM dbo.table
) AS x;
This will produce nulls for any row where there is garbage in either column. Here is a modification to your original query:
SELECT
[ITEM_NO] -- what table does this come from?
,[ITEM_DESC] -- what table does this come from?
,[HEADER_DUE_DATE] -- what table does this come from?
,D.WHS_SHORT_NAME AS [Warehouse] -- don't use single quotes for aliases!
,FPODtl.[PO_NO] AS [PO NUMBER]
,FPODtl.[PO_DATE] AS [Start]
,FPODtl.[PO_STATUS] AS [Status]
,FPODtl.[LINE_DOCK_DATE] AS [End]
,DATEDIFF
(
DAY,
CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.PO_DATE)) = 1
THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.PO_DATE)) END,
CASE WHEN ISDATE(CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) = 1
THEN CONVERT(DATETIME, CONVERT(CHAR(8), FPODtl.[LINE_DOCK_DATE])) END
)
FROM [dbo].[DS_tblFactPODtl] AS FPODtl
INNER JOIN [dbo].[DS_tblDimWhs] AS D
ON FPODtl.WAREHOUSE = D.WAREHOUSE
INNER JOIN [dbo].[DS_tblFactPO] AS FPO
ON FPODtl.PO_NO = FPO.PO_NO
WHERE FPODtl.[PO_STATUS] = 'Closed'
AND FPODtl.[LINE_DOCK_DATE] <> 0;
If the date stored as a number is like this: 20130226 for today, then the simpler way to convert to DATE or DATETIME would be:
SELECT CONVERT(DATETIME,CONVERT(VARCHAR(8),NumberDate),112)
Here is a quick formula to create a date from parts :
DateAdd( Month, (( #Year - 1900 ) * 12 ) + #Month - 1, #Day - 1 )
Simply use substrings from your original field to extract #Year, #Month and #Day. For instance, if you have a numeric like 19531231 for december 31th, 1953, you could do :
DateAdd( Month, (( SubString(Cast(DateField As Varchar(8)), 1, 4) - 1900 ) * 12 ) +
SubString(Cast(DateField As Varchar(8)), 5, 2) - 1,
SubString(Cast(DateField As Varchar(8)), 7, 2) - 1 )
I need to create a query that will sum the number of True(1) and False(0) into two separate columns from one bit field.
I'm joining 3 tables and need it to be something like:
Attribute | Class | Pass | Fail
I will be grouping on Attribute and Class.
Something like this:
SUM(CASE WHEN ColumnName = 1 THEN 1 ELSE 0 END) AS Pass,
SUM(CASE WHEN ColumnName = 0 THEN 1 ELSE 0 END) AS Fail
This works (at least in SQL 2008)
SELECT SUM(Passed + 0) PASS , SUM(1 - Passed) FAIL
I am adding 0 to Passed in the first sum as a short hand way of converting from bit to int since you can't sum bits directly.
try:
declare #table table (columnName bit)
insert into #table values (1)
insert into #table values (1)
insert into #table values (1)
insert into #table values (1)
insert into #table values (1)
insert into #table values (0)
insert into #table values (0)
insert into #table values (0)
insert into #table values (0)
SELECT
SUM(CASE WHEN ColumnName = 1 THEN 1 ELSE 0 END) AS True1
, SUM(CASE WHEN ColumnName = 0 THEN 1 ELSE 0 END ) AS False0
from #Table
OUTPUT:
True1 False0
----------- -----------
5 4
(1 row(s) affected)
SELECT
Attribute,
Class,
SUM(CASE BitField WHEN 1 THEN 1 ELSE 0 END) AS [Pass],
SUM(CASE BitField WHEN 0 THEN 1 ELSE 0 END) AS [Fail]
FROM
Table
GROUP BY
Attribute,
Class
Another option would be
SELECT Attribute, Class
COUNT(CASE WHEN ColumnName = 1 THEN 1 END) Pass,
COUNT(CASE WHEN ColumnName = 0 THEN 1 END) Fail FROM YourTable
GROUP BY Attribute, Class
there is even one more option:
SELECT
Attribute,
Class,
COUNT(BoolColumnName = 1 or NULL) Pass,
COUNT(BoolColumnName = 0 or NULL) Fail
FROM Table
GROUP BY Attribute, Class