Multiple column values in a single row - sql

I have table like this
ID Status
1 5
1 6
1 7
2 5
2 6
2 7
I need the result like below
ID col1 col2 col3
1 5 6 7
2 5 6 7
Please help me

SELECT ID,
MAX(CASE WHEN status = 5 THEN Status ELSE NULL END) col1,
MAX(CASE WHEN status = 6 THEN Status ELSE NULL END) col2,
MAX(CASE WHEN status = 7 THEN Status ELSE NULL END) col3
FROM tableNAME
GROUP BY ID
SQLFiddle Demo
using PIVOT
SELECT *
FROM (
SELECT ID, Status, CASE Status
WHEN 5 THEN 'Col1'
WHEN 6 THEN 'Col2'
WHEN 7 THEN 'Col3'
END Stat
FROM tableName
) src
PIVOT
(
MAX(Status)
FOR Stat IN ([Col1],[Col2],[Col3])
) pivotTbl
SQLFiddle Demo

Attempt for unknown count of destination columns
--Create table TESTx (id int,status int)
--insert into TESTx Values (1,5),(1,6),(1,7),(1,17),(2,5),(2,7),(2,8),(3,1),(3,5);
-
Declare #Tab Varchar(50)='##tmp' + Replace(Cast(newID() as Varchar(36)),'-','')
Declare #SQL Varchar(max)
Declare #Cols Varchar(max)
Declare #Renames Varchar(max)
Select #Cols ='Create Table ' + #Tab + '(ID int'
Select #Cols=#Cols + ',[Col'+ Cast(Status as varchar(10))+'] int'
from
(Select Distinct top 1000 Status
from
TESTx order by Status
) a
Select #Cols=#Cols +')'
Select #SQL= #Cols
+' Insert into '+#Tab +' (ID) Select Distinct ID from TESTx'
exec(#SQL)
Declare #Status int
DECLARE P_cursor CURSOR FOR
SELECT Distinct Status from TESTx
OPEN P_cursor
FETCH NEXT FROM P_cursor
INTO #Status
WHILE ##FETCH_STATUS = 0
BEGIN
Select #SQL='Update ' + #Tab + ' Set Col' + CAST(#Status as Varchar(10)) +'=' +Cast(#Status as Varchar(10))
+' from TESTx Where TESTx.ID=' + #Tab +'.ID and Testx.Status=' +Cast(#Status as Varchar(10))
Exec(#SQL)
FETCH NEXT FROM P_cursor
INTO #Status
END
CLOSE P_cursor
DEALLOCATE P_cursor
Select #SQL=' Select * from '+#Tab +' Drop Table ' + #Tab
Exec(#SQL)

Related

How to loop through a list of table names and see if a specific value in a column exists?

I have produced a table in SQL with a list of tables. This list of tables is stored under the column 'table_name'. I want to loop through each entry under 'table_name' and return a 1 if that table has a value in a specific column or 0 if that table does not have a value in a specific column.
How would I do that?
Edited With sample data
table_name
tabel1
table2
table3
table4
Pseudo Code
For i in table_name
if count(table_name["col_name"] = "value") > 0
return 1
else
return 0
Try this:
drop table if exists #t
create table #t (A int)
insert into #t
select 1
drop table if exists #t2
create table #t2 (A int)
insert into #t2
select 0
drop table if exists #tables
create table #tables (tab varchar(100))
declare
#loop table (rn int, tab varchar(100))
declare
#res table (cnt int)
declare
#i int=1
,#tab varchar (100)=''
,#query nvarchar (max)
insert into #tables
select '#t'
union all
select '#t2'
insert into #loop
select ROW_NUMBER () over (partition by (select 1) order by tab),tab from #tables
while #i<=(select max(rn) from #loop)
begin
select #tab=tab from #loop where rn=#i
set #query='select count(*) from '+#tab+' where a=1'
insert into #res
exec(#query)
if (select cnt from #res)>0 select 'Exists' else select 'Not Exists'
delete #res
set #i=#i+1
end
Assuming you have a singular column/value in question, you can try the following in SSMS:
DECLARE #Tables table ( table_name varchar(50) );
INSERT INTO #Tables VALUES
( 'Child' ), ( 'COS' ), ( 'CustomData' ), ( 'Misc' ), ( 'Misc2' );
DECLARE
#col varchar(50) = 'id', -- column to be queried
#val varchar(50) = '1', -- value to be queried
#sql varchar(MAX) = '' -- important! set to empty string;
SELECT
#sql = #sql + CASE WHEN LEN( #sql ) > 0 THEN ' UNION ' ELSE '' END
+ 'SELECT ' + QUOTENAME( table_name, '''' ) + ' AS [table_name], COUNT(*) AS [value_count] FROM [' + table_name + '] WHERE [' + #col + ']=' + QUOTENAME( #val, '''' )
FROM #Tables t WHERE EXISTS (
SELECT * FROM sys.columns c WHERE c.object_id = OBJECT_ID( t.table_name ) AND c.[name] = #col
);
EXEC( #sql );
In my environment this returns:
+------------+-------------+
| table_name | value_count |
+------------+-------------+
| Child | 1 |
| Misc | 1 |
| Misc2 | 0 |
+------------+-------------+
This is the (beautified) dynamic SQL created:
SELECT 'Child' AS [table_name], COUNT(*) AS [value_count] FROM [Child] WHERE [id]='1'
UNION
SELECT 'Misc' AS [table_name], COUNT(*) AS [value_count] FROM [Misc] WHERE [id]='1'
UNION
SELECT 'Misc2' AS [table_name], COUNT(*) AS [value_count] FROM [Misc2] WHERE [id]='1'
The EXISTS in the WHERE clause eliminates any tables that do not have the column in question, and thereby any errors related to it.

Replace null values with 0 in PIVOT

I tried to convert the (null) values with 0 (zeros) output in PIVOT function but have no success.
Below is the table and the syntax I've tried:
SELECT DISTINCT isnull([DayLoad],0) FROM #Temp1
Data in the table #Temp1:
zone dayB templt cid DayLoad
other 10 other 1 2020-05-28
other 10 other 1 2020-05-29
other 10 other 1 2020-05-30
other 10 other 1 2020-05-31
other 4 other 1 2020-06-02
other 10 other 1 2020-06-02
other 10 other 1 2020-06-01
My request:
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = COALESCE (#cols + ',[' + CONVERT(NVARCHAR, [DayLoad], 106) + ']',
'[' + CONVERT(NVARCHAR, [DayLoad], 106) + ']')
FROM (SELECT DISTINCT [DayLoad] FROM #Temp1) PV
ORDER BY [DayLoad]
DECLARE #query NVARCHAR(MAX)
SET #query = '
SELECT *
into #temptable
FROM
(
SELECT
''''+[zone]+'' '' + ''''+convert(varchar(50),[dayB])+''''+''+'' +'' ''+(case when [templt]=''Прочее'' then '''' else [templt] end)+'''' as [zone/dayB]
,[DayLoad]
,[cid]
,[dayB]
,[zone]
FROM #Temp1
) x
PIVOT
(
sum([cid])
FOR [DayLoad] IN ('+ #cols + ')
) p
select *
from #temptable
order by [zone],[dayB]
drop table #temptable
'
EXEC(#query)
DROP TABLE #Temp1
Please refer below example, when you have nulls and empty string, right option is to go with case statement,
SELECT DISTINCT case when ([DayLoad] is null or [DayLoad] = '') then 0 else [DayLoad] end FROM #Temp1

How to convert row data to column in sql server

I have a table Test with 2 column Job_name and Status contains below data,
Job_Name status
------------------------
a failed
b completed
c waiting
d failed
I want output like below,
col1 col2 col3 col4
--------------------------------------
a b c d
failed completed waiting failed
I tried using pivot , but not able to achieve the exact output .
Please let me know , how can I proceed with this.
Thanks in advance.
Try this:
declare #x table (Job_Name char(1), [status] varchar(15))
insert into #x values
('a','failed'),
('b','completed'),
('c','waiting'),
('d','failed')
select * from
(
select 'col' + CAST(ROW_NUMBER() over (order by job_name) as varchar(2)) [colName],
[status]
from #x
) as [toPivot]
pivot
(
max([status])
for
colName in([col1],[col2],[col3],[col4])
) as [p1]
union all
select * from
(
select 'col' + CAST(ROW_NUMBER() over (order by job_name) as varchar(2)) [colName],
Job_Name
from #x
) as [toPivot]
pivot
(
max([job_name])
for
colName in([col1],[col2],[col3],[col4])
) as [p2]
Using a Dynamic Pivot
SET NOCOUNT ON
IF OBJECT_ID ('tempdb..##Tmp') IS NOT NULL DROP TABLE ##Tmp
DECLARE #sql NVARCHAR(MAX)
DECLARE #cols nvarchar(max) = ''
DECLARE #hdrs nvarchar(max) = ''
DECLARE #Cols1 nvarchar(max) = ''
; WITH T (JOb_Name , Status) as
(
SELECT 'a' ,'failed'
UNION ALL
SELECT 'b' ,'completed'
UNION ALL
SELECT 'c' ,'waiting'
UNION ALL
SELECT 'd' , 'failed'
)
SELECT *
INTO ##Tmp
FROM t
SELECT #hdrs += ','+QUOTENAME(JOb_Name) + ' AS Col_'+ CAST(ROW_NUMBER () OVER(ORDER BY job_Name) AS nvarchar(5))
FROM ##Tmp
ORDER BY JOb_Name
SET #hdrs = STUFF(#hdrs,1,1,'')
SELECT #cols += ','+QUOTENAME(JOb_Name)
FROM ##Tmp
ORDER BY JOb_Name
SET #cols = STUFF(#Cols ,1,1,'')
SELECT #Cols1 += ','+QUOTENAME(Cols)
FROM
(
SELECT Job_Name, 'Col_' + CAST(ROW_NUMBER () OVER(ORDER BY job_Name) AS nvarchar(5)) Cols
FROM ##Tmp
) X
SET #Cols1 = STUFF (#cols1,1,1,'')
SET #sql =
'
SELECT *
FROM
(
SELECT Job_Name, ''Col_'' + CAST(ROW_NUMBER () OVER(ORDER BY job_Name) AS nvarchar(5)) Cols
FROM ##Tmp
) x
PIVOT (
MAX(Job_Name) FOR Cols IN ('+#cols1+')
) P
UNION ALL
SELECT '+#hdrs+'
FROM ##Tmp
PIVOT (
MAX(Status) FOR Job_Name IN ('+#cols+')
) P
'
exec sp_executesql #sql
DROP TABLE ##Tmp

Selecting columns from a query

I'm using a request to get a collection of columns name:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE [...]
From this collection, I'd like to count every not null, not empty value from the original table group by column name.
Let's say I have a table containing
COL1 | COL2 | COL3
------------------
VAL1 | VAL2 | NULL
VAL3 | | VAL4
VAL5 | |
I'm looking for a request to get:
COL1 | 3
COL2 | 1
COL2 | 1
It's for analytics purpose.
Thanks for your help!
Here is a simple process. Run the following query:
SELECT 'SELECT ''' + COLUMN_NAME + ''', COUNT(['+COLUMN_NAME']) as NotNull FROM [' +SCHEMA_NAME+ '].['+TABLE_NAME+ '] union all '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE [...]
Copy the results into a query window, remove the final union all, and run the query.
The below code seems to work for your issue
create table sample
(
col1 varchar(10),
col2 varchar(10),
col3 varchar(10)
)
INSERT INTO sample (COL1,COL2,COL3) VALUES ('VAL1 ',' VAL2 ',NULL);
INSERT INTO sample (COL1,COL2,COL3) VALUES ('VAL3 ',' ',' VAL4');
INSERT INTO sample (COL1,COL2,COL3) VALUES ('VAL5 ',' ',' ');
DECLARE #cols1 NVARCHAR(MAX);
DECLARE #sql NVARCHAR(MAX);
SELECT #cols1 = STUFF((
SELECT ', COUNT(CASE WHEN len(['+ t1.NAME + '])!=0 THEN 1 END) AS ' + t1.name
FROM sys.columns AS t1
WHERE t1.object_id = OBJECT_ID('sample')
--ORDER BY ', COUNT([' + t1.name + ']) AS ' + t1.name
FOR XML PATH('')
), 1, 2, '');
SET #sql = '
SELECT ' + #cols1 + '
FROM sample
'
EXEC(#sql)
Hereis my little longer take on this:
declare #cols table (colID integer, colName varchar(50))
declare #results table (colName nvarchar(50), valueCount bigint)
-- table name
declare #tableName nvarchar(50) = 'INSERT TABLE NAME HERE'
-- select column names from table
insert into #cols
select column_id, name from sys.columns where object_id = object_id(#tableName) order by column_id
declare #currentColID int = 0
declare #currentName nvarchar(50) = ''
declare #currentCount bigint = 0
declare #sql nvarchar(max) -- where the dynamic sql will be stored
-- go through all columns
while (1 = 1)
begin
-- step by id
select top 1 #currentColID = c.colID, #currentName = c.colName from #cols c
where c.colid > #currentColID order by c.colID
if ##ROWCOUNT = 0 break;
-- dynamic query to get non-empty, not-null counts
select #sql = 'select #p1=COUNT(' + #currentName + ') from ' + #tableName +
' where ' + #currentName + ' is not null or LEN(' + #currentName + ') > 0'
exec sp_executesql #sql, N'#p1 bigint output', #p1 = #currentCount output
-- insert result to buffer
insert into #results values (#currentName, #currentCount)
end
-- print the buffer
select * from #results
Have fun :)

Count NULL Values from multiple columns with SQL

I have 3 columns let say A, B, and C. I need to count the NULL values in each column.
For example:
A | B | C
-------------
1 |NULL| 1
1 | 1 | NULL
NULL| 1 | 1
NULL|NULL| 1
Should output:
A | B | C
---------------
2 | 2 | 1
I've tried count, sum, sub-queries but nothing has worked for me yet. Any input would be appreciated!
SELECT COUNT(*)-COUNT(A) As A, COUNT(*)-COUNT(B) As B, COUNT(*)-COUNT(C) As C
FROM YourTable;
For SQL SERVER you can use the following:
SET NOCOUNT ON
DECLARE #Schema NVARCHAR(100) = '<Your Schema>'
DECLARE #Table NVARCHAR(100) = '<Your Table>'
DECLARE #sql NVARCHAR(MAX) =''
IF OBJECT_ID ('tempdb..#Nulls') IS NOT NULL DROP TABLE #Nulls
CREATE TABLE #Nulls (TableName sysname, ColumnName sysname , ColumnPosition int ,NullCount int , NonNullCount int)
SELECT #sql += 'SELECT '''+TABLE_NAME+''' AS TableName , '''+COLUMN_NAME+''' AS ColumnName, '''+CONVERT(VARCHAR(5),ORDINAL_POSITION)+''' AS ColumnPosition, SUM(CASE WHEN '+COLUMN_NAME+' IS NULL THEN 1 ELSE 0 END) CountNulls , COUNT(' +COLUMN_NAME+') CountnonNulls FROM '+QUOTENAME(TABLE_SCHEMA)+'.'+QUOTENAME(TABLE_NAME)+';'+ CHAR(10)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = #Schema
AND TABLE_NAME = #Table
INSERT INTO #Nulls
EXEC sp_executesql #sql
SELECT *
FROM #Nulls
DROP TABLE #Nulls
you will receive a result set with the count of Null values and non null values in each column of you table
You can use an aggregate function with a CASE expression:
select
sum(case when a is null then 1 else 0 end) A,
sum(case when b is null then 1 else 0 end) B,
sum(case when c is null then 1 else 0 end) C
from yt
See Demo
SELECT
(SELECT count(*) FROM my_table WHERE A is NULL) as A,
(SELECT count(*) FROM my_table WHERE B is NULL) as B,
(SELECT count(*) FROM my_table WHERE C is NULL) as C
select
sum(case when a is null then 1 else 0 end) as a_null_count,
sum(case when b is null then 1 else 0 end) as b_null_count,
sum(case when c is null then 1 else 0 end) as c_null_count
from table
I am very late to this, but if you don't want to manually list out all the column names and still want to get a table, you can do this in SQL Server (Just replace testTable with your actual table):
--Creates the table the poster wanted
CREATE TABLE testTable (A int, B int, C int)
INSERT INTO testTable (A, C) VALUES (1,1)
INSERT INTO testTable (A, B) VALUES (1,1)
INSERT INTO testTable (B, C) VALUES (1,1)
INSERT INTO testTable (C) VALUES (1)
--Creates the output table which will consist of each column name and the amount of nulls
CREATE TABLE ColumnNames (
ID int IDENTITY(1,1) PRIMARY KEY,
[name] varchar(max),
nullAmount int
)
INSERT INTO ColumnNames ([name])
SELECT [name] FROM sys.columns WHERE object_id = OBJECT_ID('dbo.testTable')
DECLARE #columnIndex INT = 1
WHILE #columnIndex <= ( SELECT COUNT(*) FROM dbo.ColumnNames )
BEGIN
DECLARE #colName nvarchar(max) = (SELECT [name] FROM ColumnNames WHERE ID = #columnIndex)
EXEC('SELECT ' + #colName + ' INTO colTable FROM testTable')
DECLARE #SQL nvarchar(max) = N'UPDATE ColumnNames SET nullAmount = (SELECT COUNT(1) - COUNT(' + quotename(#colName) + ') FROM colTable) WHERE ID = #columnIndex'
EXEC SP_EXECUTESQL #SQL, N'#columnIndex int', #columnIndex
DROP TABLE colTable
SET #columnIndex = #columnIndex + 1
END
--Select the output table and get null info
SELECT * FROM ColumnNames