Pivot function returning null values - sql

I want to show all three rows in 1st row so i used pivot in the query
**output pic is attached **
SELECT [Container Number],ReadTimee,Locationn,Trailer FROM
(SELECT [Container Number],ReadTime,Location FROM #temp )as Tab1
PIVOT
(
MAX(ReadTime) FOR Location IN (Trailer,ReadTimee,Locationn)) AS Tab2
But using above query returning null
.The output pic is shown below
I want a output Like this
ReadTime Location Trailer Container Number ReadTime Location Trailer Container Number ReadTime Location Trailer Container Number
2019-02-27 03:17:21.033 CUSTOM 1 ZIMU1374787,TRHU3437713 2019-02-27 06:10:35.470 ZERO 1 ZIMU1374787,TRHU3437713 2019-02-27 07:30:47.407 CFS 1 ZIMU1374787,TRHU3437713

Try this:
SELECT Trailer, [Container Number], [CUSTOM] = MAX(CASE WHEN Location = 'CUSTOM' THEN ReadTime ELSE NULL END),
[ZERO] = MAX(CASE WHEN Location = 'ZERO' THEN ReadTime ELSE NULL END),
[CFS] = MAX(CASE WHEN Location = 'CFS' THEN ReadTime ELSE NULL END)
FROM #tmp
GROUP BY Trailer, [Container Number]
Above query returns:
Trailer Container Number CUSTOM ZERO CFS
1 ZIMU1374787,TRHU3437713 2019-02-27 03:17:21.033 2019-02-27 06:10:35.470 2019-02-27 07:30:47.407

You can use MAX method to get necessary columns:
SELECT
MAX(CASE WHEN q.RowNumber = 1 THEN q.ReadTime ELSE NULL END) AS ReadTime
, MAX(CASE WHEN q.RowNumber = 1 THEN q.Location ELSE NULL END) AS Location
, MAX(CASE WHEN q.RowNumber = 1 THEN q.Trailer ELSE NULL END) AS Trailer
, MAX(CASE WHEN q.RowNumber = 1 THEN q.ContainerNumber ELSE NULL END) AS ContainerNumber
, MAX(CASE WHEN q.RowNumber = 2 THEN q.ReadTime ELSE NULL END) AS ReadTime
, MAX(CASE WHEN q.RowNumber = 2 THEN q.Location ELSE NULL END) AS Location
, MAX(CASE WHEN q.RowNumber = 2 THEN q.Trailer ELSE NULL END) AS Trailer
, MAX(CASE WHEN q.RowNumber = 2 THEN q.ContainerNumber ELSE NULL END) AS ContainerNumber
, MAX(CASE WHEN q.RowNumber = 3 THEN q.ReadTime ELSE NULL END) AS ReadTime
, MAX(CASE WHEN q.RowNumber = 3 THEN q.Location ELSE NULL END) AS Location
, MAX(CASE WHEN q.RowNumber = 3 THEN q.Trailer ELSE NULL END) AS Trailer
, MAX(CASE WHEN q.RowNumber = 3 THEN q.ContainerNumber ELSE NULL END) AS ContainerNumber
FROM
(
SELECT
*
, ROW_NUMBER() OVER(PARTITION BY T.Trailer ORDER BY T.Trailer) AS RowNumber
FROM #Table AS T
)AS q
Let me show an example:
DECLARE #Table TABLE
(
ReadTime DATETIME,
[Location] VARCHAR(50),
Trailer INT,
ContainerNumber VARCHAR(50)
)
INSERT INTO #Table
(
ReadTime,
Location,
Trailer,
ContainerNumber
)
VALUES
( '2019-02-23 12:22:35.490', 'CUSTOM', 1, 'ZIMU1' )
, ( '2019-02-24 12:22:35.490', 'ZERO', 1, 'ZIMU2' )
, ( '2019-02-25 12:22:35.490', 'CFS', 1, 'ZIMU3')
And use the above query to get the desired output:

Related

SQL query - not null

I have sql query:
Select id
,MAX(CASE WHEN (pos = "10") THEN date ELSE NULL END) position10
,MAX(CASE WHEN (pos = "18") THEN date ELSE NULL END) position18
,MAX(CASE WHEN (pos = "20") THEN date ELSE NULL END) position20
FROM table
WHERE
date BETWEEN "${od=2021-05-01 00:00:01}" AND "${do=2021-07-01 00:00:01}"
AND pos IN('10','18','20')
group by id
I got this table
id
position10
position20
position30
1
2021-05-02
2021-05-02
2021-05-3
2
2021-05-15
2021-05-16
2021-05-18
3
2021-07-08
NULL
NULL
And I want lines where NULL values are not picked up.
A try this:
SELECT * FROM (
Select id
,MAX(CASE WHEN (pos = "10") THEN date ELSE NULL END) position10
,MAX(CASE WHEN (pos = "18") THEN date ELSE NULL END) position18
,MAX(CASE WHEN (pos = "20") THEN date ELSE NULL END) position20
FROM table
WHERE
date BETWEEN "${od=2021-05-01 00:00:01}" AND "${do=2021-07-01 00:00:01}"
AND pos IN('10','18','20')
group by id )T
WHERE (position10 IS NOT NULL)
OR (position18 IS NOT NULL)
OR (position20 IS NOT NULL)
But it still chooses to me where the NULL value appears somewhere.
You need to change OR to AND in WHERE clause
SELECT * FROM (
Select id
,MAX(CASE WHEN (pos = "10") THEN date ELSE NULL END) position10
,MAX(CASE WHEN (pos = "18") THEN date ELSE NULL END) position18
,MAX(CASE WHEN (pos = "20") THEN date ELSE NULL END) position20
FROM table
WHERE
date BETWEEN "${od=2021-05-01 00:00:01}" AND "${do=2021-07-01 00:00:01}"
AND pos IN('10','18','20')
group by id )T
WHERE position10 IS NOT NULL
AND position18 IS NOT NULL
AND position20 IS NOT NULL

records with same account ID with multiple values as one table with each value in a separate field

I have a table that looks like this
Table: AcctPrograms
Acct ProgramOptions Date_End
100 A 2016-09-01 00:00:00.0000000
100 B 2017-01-01 00:00:00.0000000
101 B 2017-01-01 00:00:00.0000000
101 C 2018-01-01 00:00:00.0000000
101 D 2017-01-01 00:00:00.0000000
102 C 2018-01-01 00:00:00.0000000
103 F 2016-06-01 00:00:00.0000000
103 G 2015-12-14 00:00:00.0000000
...
I want to create a view vw_AcctProgramOptions that looks like this:
Acct ProgramOption1 ProgramOption2 ... ProgramOption10
100 A B
101 B C
102 C
103 F G
...
The catch is that an acct in the AcctPrograms table can have MORE than 10 options but I'm only interested in collecting the first 10 order by MaxDate(Date_End) from the AcctPrograms table.
Any help would be greatly appreciated. I've been working on this for a couple of days and can't seem to get it working.
Thanks so much in advance.
EDIT:
Using MSSQL 2008
Use ROW_NUMBER to order ProgramOptions grouped by Acct and pull the first 10 in the order in the form of columns by using CASE WHEN statements.
SELECT A.ACCT,
MAX(CASE WHEN A.RNUM = 1 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION1,
MAX(CASE WHEN A.RNUM = 2 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION2,
MAX(CASE WHEN A.RNUM = 3 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION3,
MAX(CASE WHEN A.RNUM = 4 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION4,
MAX(CASE WHEN A.RNUM = 5 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION5,
MAX(CASE WHEN A.RNUM = 6 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION6,
MAX(CASE WHEN A.RNUM = 7 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION7,
MAX(CASE WHEN A.RNUM = 8 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION8,
MAX(CASE WHEN A.RNUM = 9 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION9,
MAX(CASE WHEN A.RNUM = 10 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION10
FROM
(SELECT
ACCT, PROGRAMOPTIONS, DATE_END, ROW_NUMBER() OVER (PARTITION BY ACCT ORDER BY DATE_END) AS RNUM
FROM
ACCTPROGRAMS A
)
GROUP BY A.ACCT;
--Vashi's answer with a the A a little bit lower at the query
--try the query
create table #table
(
Acct int,
ProgramOptions varchar(1),
Date_End datetime
)
insert into #table
(
Acct,
ProgramOptions,
Date_End
)
values
( 100, 'A', '2016-09-01 00:00:00' ),
( 100, 'B', '2017-01-01 00:00:00' ),
( 101, 'B', '2017-01-01 00:00:00' ),
( 101, 'C', '2018-01-01 00:00:00' ),
( 101, 'D', '2017-01-01 00:00:00' ),
( 102, 'C', '2018-01-01 00:00:00' ),
( 103, 'F', '2016-06-01 00:00:00' ),
( 103, 'G', '2015-12-14 00:00:00' )
SELECT A.ACCT,
MAX(CASE WHEN A.RNUM = 1 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION1,
MAX(CASE WHEN A.RNUM = 2 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION2,
MAX(CASE WHEN A.RNUM = 3 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION3,
MAX(CASE WHEN A.RNUM = 4 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION4,
MAX(CASE WHEN A.RNUM = 5 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION5,
MAX(CASE WHEN A.RNUM = 6 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION6,
MAX(CASE WHEN A.RNUM = 7 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION7,
MAX(CASE WHEN A.RNUM = 8 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION8,
MAX(CASE WHEN A.RNUM = 9 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION9,
MAX(CASE WHEN A.RNUM = 10 THEN A.PROGRAMOPTIONS ELSE NULL END) AS PROGRAMOPTION10
FROM
(SELECT
ACCT, PROGRAMOPTIONS, DATE_END, ROW_NUMBER() OVER (PARTITION BY ACCT ORDER BY DATE_END) AS RNUM
FROM
#table
) A
GROUP BY A.ACCT;
drop table #table

SQL/HIVE - resolve issue (small change) - Partition

I have the below code, which mostly works correctly with some other scenarios I tested.
However, for the example below I am trying to count the number for N-CO (non completions) until completion but it return 5 instead of 3.
And i am trying to create another column to count the PARTIALLY which is 2.
Any once have some input as to why?
What do I need to change?
CREATE TABLE #temp
(
Identifier varchar(20)NOT NULL
,CreatedDate DATETIME NOT NULL
,CompletedDate DATETIME NOT NULL
,SN_Type varchar(20) NOT NULL
,SN_Status varchar(20) NOT NULL
)
;
INSERT INTO #temp
VALUES('64074558792','20160729','20160805','Re-Activattion','N-CO');
INSERT INTO #temp
VALUES('64074558792','20160729','20160805','Re-Activattion','PARTIALLY');
INSERT INTO #temp
VALUES('64074558792','20160809','20160809','Re-Activattion','PARTIALLY');
INSERT INTO #temp
VALUES('64074558792','20160810','20160810','Re-Activattion','N-CO');
INSERT INTO #temp
VALUES('64074558792','20160812','20160812','Re-Activattion','N-CO');
INSERT INTO #temp
VALUES('64074558792','20160811','20160811','Re-Activattion','COMP');
INSERT INTO #temp
VALUES('64074558792','20160811','20160813','Re-Activattion','N-CO');
;
WITH Src AS (
SELECT Identifier, CreatedDate, CompletedDate, SN_Type, SN_Status,
ROW_NUMBER() OVER(PARTITION BY Identifier ORDER BY CreatedDate, CASE WHEN SN_Status = 'COMP' THEN 1 ELSE 0 END, CompletedDate) AS rn,
ROW_NUMBER() OVER(PARTITION BY Identifier ORDER BY CreatedDate, CASE WHEN SN_Status = 'COMP' THEN 1 ELSE 0 END, CompletedDate) -
ROW_NUMBER() OVER(PARTITION BY Identifier,CASE WHEN SN_Status = 'COMP' THEN 1 ELSE 0 END ORDER BY CreatedDate, CompletedDate) AS grp
FROM #temp
),
Grouped AS (
SELECT Identifier, CASE WHEN SN_Status = 'COMP' THEN 1 ELSE 0 END AS IsCOMP,
MIN(CreatedDate) AS StartDate,
COUNT(*) AS [RE-AN NCO #],
MAX(rn) AS LastRn
FROM Src
GROUP BY Identifier, CASE WHEN SN_Status = 'COMP' THEN 1 ELSE 0 END, grp
),
grouped2 AS (SELECT Identifier, MAX(rn) AS maxRN
FROM [Src]
GROUP BY [Src].[Identifier])
SELECT s.Identifier,
CASE WHEN isComp = 0
THEN
CAST(DATEDIFF(day,g.StartDate,s.CreatedDate) AS VARCHAR(25))
ELSE
'NOT COMPLETED'
END AS RE_ACT_COMPLETION_TIME,
g.[RE-AN NCO #]
FROM Src s
INNER JOIN Grouped g ON g.Identifier = s.Identifier
AND g.LastRn + 1 = s.rn
JOIN grouped2 g2 ON [g2].[Identifier] = [s].[Identifier]
WHERE s.SN_Status = 'COMP'
OR (SN_Status <> 'COMP' AND maxRN = [s].[rn])
ORDER BY rn;
DROP TABLE #temp
select Identifier
,COMP_id
,count(case when SN_Status = 'N-CO' then 1 end) as count_N_CO
,count(case when SN_Status = 'PARTIALLY' then 1 end) as count_PARTIALLY
,count(case when SN_Status = 'COMP' then 1 end) as is_COMP
from (select Identifier
,SN_Status
,count(case when SN_Status = 'COMP' then 1 end) over
(
partition by Identifier
order by CreatedDate, case when SN_Status = 'COMP' then 1 else 0 end, CompletedDate
rows between unbounded preceding and 1 preceding
) + 1 as COMP_id
from #temp
) t
group by Identifier
,COMP_id
+-------------+---------+------------+-----------------+---------+
| Identifier | COMP_id | count_N_CO | count_PARTIALLY | is_COMP |
+-------------+---------+------------+-----------------+---------+
| 64074558792 | 1 | 3 | 2 | 1 |
| 64074558792 | 2 | 1 | 0 | 0 |
+-------------+---------+------------+-----------------+---------+

Case statement with grouping

Can you help me write a SELECT statement that returns a single row having columns for each TypeId involved for the transaction number 55?
CREATE TABLE Types
(
Id INT IDENTITY(1,1) NOT NULL,
Name VARCHAR(100) NOT NULL,
CONSTRAINT PK_Types PRIMARY KEY CLUSTERED(Id)
)
GO
INSERT INTO Types
VALUES
('Type1')
,('Type2')
,('Type3')
,('Type4')
,('Type5')
GO
CREATE TABLE Transactions
(
Id INT IDENTITY(1000,1) NOT NULL,
TypeId INT NULL,
TransactionNumber INT NOT NULL,
Amount MONEY NULL,
DateRecorded DATETIME2 NOT NULL,
CONSTRAINT PK_Transactions PRIMARY KEY CLUSTERED(Id),
CONSTRAINT FK_Types FOREIGN KEY(TypeId) REFERENCES Types(Id)
)
GO
INSERT INTO Transactions
VALUES
(1,55,2555.50,SYSDATETIME())
,(3,55,3555.50,SYSDATETIME())
,(4,55,4555.50,SYSDATETIME())
,(5,55,5555.50,SYSDATETIME())
GO
I need a single row returned for each transaction number in the Transactions table.
What I already tried:
SELECT TransactionNumber
,(CASE WHEN TypeId = 1 THEN Amount ELSE 0 END) AS Type1
,(CASE WHEN TypeId = 2 THEN Amount ELSE 0 END) AS Type2
,(CASE WHEN TypeId = 3 THEN Amount ELSE 0 END) AS Type3
,(CASE WHEN TypeId = 4 THEN Amount ELSE 0 END) AS Type4
,(CASE WHEN TypeId = 5 THEN Amount ELSE 0 END) AS Type5
FROM Transactions
SELECT TransactionNumber
,sum(CASE WHEN TypeId = 1 THEN Amount ELSE 0 END) AS Type1
,sum(CASE WHEN TypeId = 2 THEN Amount ELSE 0 END) AS Type2
,sum(CASE WHEN TypeId = 3 THEN Amount ELSE 0 END) AS Type3
,sum(CASE WHEN TypeId = 4 THEN Amount ELSE 0 END) AS Type4
,sum(CASE WHEN TypeId = 5 THEN Amount ELSE 0 END) AS Type5
FROM Transactions group by TransactionNumber;
I think you can do a PIVOT to get required output:
SELECT *
FROM (
SELECT ty.NAME, ISNULL(Amount,0)Amount
FROM TRANSACTIONS t
INNER JOIN Types ty ON ty.Id = t.TypeId
WHERE TransactionNumber = 55
) sub
PIVOT(
SUM(Amount) FOR [Name] IN ([Type1], [Type2], [Type3], [Type4], [Type5])
) AS pivottable
SQL Fiddle
With conditional aggregation:
select Id,
sum(case TypeId when 1 then Amount end) Type1,
sum(case TypeId when 2 then Amount end) Type2,
...
from Transactions
group by Id
I think this would be the query you are looking for:
SELECT
COUNT(CASE WHEN TypeID = 1 THEN 1 ELSE NULL END) '# Transactions Type 1'
, COUNT(CASE WHEN TypeID = 2 THEN 1 ELSE NULL END) '# Transactions Type 2'
, COUNT(CASE WHEN TypeID = 3 THEN 1 ELSE NULL END) '# Transactions Type 3'
, COUNT(CASE WHEN TypeID = 4 THEN 1 ELSE NULL END) '# Transactions Type 4'
, COUNT(CASE WHEN TypeID = 5 THEN 1 ELSE NULL END) '# Transactions Type 5'
FROM TRANSACTIONS
Where TransactionNumber = 55
You can find a working SQLFiddle here.
EDIT:
After you comment I think what you are actually looking for is SUM().
SELECT TransactionNumber
, SUM(CASE WHEN TypeId = 1 THEN Amount ELSE 0 END) AS Type1
, SUM(CASE WHEN TypeId = 2 THEN Amount ELSE 0 END) AS Type2
, SUM(CASE WHEN TypeId = 3 THEN Amount ELSE 0 END) AS Type3
, SUM(CASE WHEN TypeId = 4 THEN Amount ELSE 0 END) AS Type4
, SUM(CASE WHEN TypeId = 5 THEN Amount ELSE 0 END) AS Type5
FROM Transactions
GROUP BY TransactionNumber
SQLFiddle for 2nd query here.

JOIN always the default value, else join the match value

I have the following SQL Server Query
select r.isactive,r.workingyear,r.startperiod,r.endperiod,r.anniversary
from setup_holiday_policy t cross apply
(select data
from dbo.Split(t.scheduleapplication, ',')
) di cross apply
(select max(case when did.id = 1 then did.data end) as isactive,
max(case when did.id = 2 then did.data end) as workingyear,
max(case when did.id = 3 then did.data end) as anniversary,
max(case when did.id = 4 then did.data end) as startperiod,
max(case when did.id = 5 then did.data end) as endperiod
from dbo.Split(di.data,':') did
) r
WHERE r.workingyear = #employeeworkingyears
The policy table can have a 0 value in the workingyear field. Meaning that when this field has 0 then is the default record I should return.
setup_holiday_policy
So, if #employeeworkingyears = 2 and there is no workingyears = 2 in setup_holiday_policy I should return the default row that has the 0 value in workingyears field.
This is a sample of the rows returned.
Any clue how to achieve this?
If only one row is going to be returned (as suggested by the sample data), you can do this using top:
select top 1 r.isactive,r.workingyear,r.startperiod,r.endperiod,r.anniversary
from setup_holiday_policy t cross apply
(select data
from dbo.Split(t.scheduleapplication, ',')
) di cross apply
(select max(case when did.id = 1 then did.data end) as isactive,
max(case when did.id = 2 then did.data end) as workingyear,
max(case when did.id = 3 then did.data end) as anniversary,
max(case when did.id = 4 then did.data end) as startperiod,
max(case when did.id = 5 then did.data end) as endperiod
from dbo.Split(di.data,':') did
) r left outer join
(select #employeeworkingyears as employeeworkingyears
) e
on
WHERE r.workingyear in (#employeeworkingyears, 0)
order by r.workingyear desc;