SQL Server : UNION, Columns with Data, Drop the Columns Without - sql-server

I have two tables, LYEAR and CYEAR:
[SKU],[Title],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12]
Columns [SKU],[Title],[1],[2],[3],[4],[5],[6],[7],[8] are populated with information from the CYEAR table and [SKU],[Title],[9],[10],[11],[12] from the LYEAR table.
How would I merge the two tables, so that there are columns with NULL values are dropped, leaving me with one row per SKU?
I have got this far:
WITH LYEAR_ORG ([SKU],[Title],[QTY],[DATE]) AS
(
SELECT
T1.ItemNumber, T1.ItemTitle, (SUM(T2.nqty)) AS [UNITS],
CONVERT(VARCHAR(2), (MONTH(T3.dProcessedOn)))
FROM
StockItem T1
LEFT OUTER JOIN
OrderItem T2 ON T1.pkstockItemId = T2.fkStockItemID_processed
LEFT JOIN
[Order] T3 ON T3.pkOrderID = T2.fkOrderID
WHERE
(YEAR(T3.dProcessedOn)) = (YEAR(getdate())-1)
AND (MONTH(T3.dProcessedOn)) > (MONTH(getdate())-1)
GROUP BY
T1.ItemNumber, T1.ItemTitle,
CONVERT(VARCHAR(2), (MONTH(T3.dProcessedOn)))
),
CYEAR_ORG ([SKU],[Title],[QTY],[DATE]) AS
(
SELECT T1.ItemNumber, T1.ItemTitle, (SUM(T2.nqty)) AS [UNITS], CONVERT(varchar(2),(MONTH(T3.dProcessedOn)))
FROM StockItem T1
LEFT OUTER JOIN OrderItem T2 ON T1.pkstockItemId = T2.fkStockItemID_processed
LEFT JOIN [Order] T3 ON T3.pkOrderID = T2.fkOrderID
WHERE (YEAR(T3.dProcessedOn)) = (YEAR(getdate())-1)
AND (MONTH(T3.dProcessedOn)) < (MONTH(getdate()))
GROUP BY T1.ItemNumber, T1.ItemTitle, CONVERT(varchar(2),(MONTH(T3.dProcessedOn)))
),
LYEAR ([SKU],[Title],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12]) AS (
SELECT *
FROM LYEAR_ORG
PIVOT ( MAX(QTY) FOR DATE in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) as LYEAR_ORDERS
),
CYEAR ([SKU],[Title],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12]) AS (
SELECT *
FROM CYEAR_ORG
PIVOT ( MAX(QTY) FOR DATE in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) as CYEAR_ORDERS
)
SELECT * FROM LYEAR
UNION ALL
SELECT * FROM CYEAR
I am unable to use INSERT INTO as this is a limitation on the Linnworks platform I am working on, it is SQL Server.

On the assumption that LYEAR columns 1-8 are all NULL, and so are CYEAR 9-12, a JOIN with a ton of COALESCEs, rather than a UNION will get you where you want to be. If, though, there are values for both years in any columns, this will go sideways.
SELECT
l.[SKU]
,l.[Title]
,COALESCE(l.[1], c.[1]) AS [1]
,COALESCE(l.[2], c.[2]) AS [2]
,COALESCE(l.[3], c.[3]) AS [3]
,COALESCE(l.[4], c.[4]) AS [4]
,COALESCE(l.[5], c.[5]) AS [5]
,COALESCE(l.[6], c.[6]) AS [6]
,COALESCE(l.[7], c.[7]) AS [7]
,COALESCE(l.[8], c.[8]) AS [8]
,COALESCE(l.[9], c.[9]) AS [9]
,COALESCE(l.[10], c.[10]) AS [10]
,COALESCE(l.[11], c.[11]) AS [11]
,COALESCE(l.[12], c.[12]) AS [12]
FROM
LYEAR AS l
JOIN
CYEAR AS c
ON
c.SKU = l.SKU
AND c.Title = l.Title;

Here's a solution that will allow for there to be data in both LYEAR and CYEAR, and to switch from one to the other based on the month of the year:
SELECT SKU,
Title,
CASE WHEN DATEPART(MM, GETDATE()) > 1
THEN LYEAR.1
ELSE CYEAR.1
END,
CASE WHEN DATEPART(MM, GETDATE()) > 2
THEN LYEAR.2
ELSE CYEAR.2
END,
CASE WHEN DATEPART(MM, GETDATE()) > 3
THEN LYEAR.3
ELSE CYEAR.3
END,
CASE WHEN DATEPART(MM, GETDATE()) > 4
THEN LYEAR.4
ELSE CYEAR.4
END
--Add rest of CASE statements for remaining months
FROM LYEAR AS L
JOIN CYEAR AS C
ON L.SKU = C.SKU
AND L.Title = C.Title

Related

How to replace null values to 0 in pivot table using sql server

I am trying to replace 0.00 in place of null in the pivot table. The query is as below
SELECT *
FROM (
SELECT [dbo].[CLOI_ClientOrderItems].[cl_id] 'Customer Id'
,[dbo].[CL_Clients].[cl_name] 'Customer Name'
,FORMAT(in_date_issued, 'MMMM') AS 'Month'
,[dbo].[IN_Invoices].[in_total] AS 'Invoice_Total'
FROM [dbo].[CLOI_ClientOrderItems]
INNER JOIN [dbo].[CL_Clients] ON [dbo].[CLOI_ClientOrderItems].[cl_id] = [dbo].[CL_Clients].[cl_id]
INNER JOIN [dbo].[IN_Invoices] ON [dbo].[CLOI_ClientOrderItems].[MasterOrderId] = [dbo].[IN_Invoices].[MasterOrderId]
WHERE YEAR(in_date_issued) = #in_date_issued
AND cl_system = 'DPO'
) AS s
PIVOT(Sum(Invoice_Total) FOR [Month] IN (
january
,february
,march
,april
,may
,june
,july
,august
,september
,october
,november
,december
)) AS pvt
Simply use ISNULL/COALESCE:
SELECT col_names,
ISNULL(january, 0) AS january,
COALESCE(february, 0) AS february,
...
FROM ...

Select from same column under different conditons

I need to join these two tables. I need to select occurrences where:
ex_head of_family_active = 1 AND tax_year = 2017
and also:
ex_head of_family_active = 0 AND tax_year = 2016
The first time I tried to join these two tables I got the warehouse data
dbo.tb_master_ascend AND warehouse_data.dbo.tb_master_ascend in the from clause have the same exposed names. As the query now shown below, I get a syntax error on the "where". What am I doing wrong? Thank you
use [warehouse_data]
select
parcel_number as Account,
pact_code as type,
owner_name as Owner,
case
when ex_head_of_family_active >= 1
then 'X'
else ''
end 'Head_Of_Fam'
from
warehouse_data.dbo.tb_master_ascend
inner join
warehouse_data.dbo.tb_master_ascend on parcel_number = parcel_number
where
warehouse_data.dbo.tb_master_ascend.tax_year = '2016'
and ex_head_of_family_active = 0
where
warehouse_data.dbo.tb_master_ascend.t2.tax_year = '2017'
and ex_head_of_family_active >= 1
and (eff_from_date <= getdate())
and (eff_to_date is null or eff_to_date >= getdate())
#marc_s I changed the where statements and updated my code however the filter is not working now:
use [warehouse_data]
select
wh2.parcel_number as Account
,wh2.pact_code as Class_Type
,wh2.owner_name as Owner_Name
,case when wh2.ex_head_of_family_active >= 1 then 'X'
else ''
end 'Head_Of_Fam_2017'
from warehouse_data.dbo.tb_master_ascend as WH2
left join warehouse_data.dbo.tb_master_ascend as WH1 on ((WH2.parcel_number = wh1.parcel_number)
and (WH1.tax_year = '2016')
and (WH1.ex_head_of_family_active is null))
where WH2.tax_year = '2017'
and wh2.ex_head_of_family_active >= 1
and (wh2.eff_from_date <= getdate())
and (wh2.eff_to_date is null or wh2.eff_to_date >= getdate())
I would use a CTE to get all your parcels that meet your 2016 rules.
Then join that against your 2017 rules on parcel ID.
I'm summarizing:
with cte as
(
select parcelID
from
where [2016 rules]
group by parcelID --If this isn't unique you will cartisian your results
)
select columns
from table
join cte on table.parcelid=cte.parcelID
where [2017 rules]

SSRS:How to return count of events per day for Month

I have a table with the following information
ID,DateTime,EventType
1,6/5/2013 9:35:00,B
1,6/5/2013 9:35:24,A
2,6/5/2013 9:35:36,B
3,6/5/2013 9:36:11,D
2,6/5/2013 9:39:16,A
3,6/5/2013 9:40:48,B
4,7/5/2013 9:35:19,B
4,7/5/2013 9:35:33,A
5,7/5/2013 9:35:53,B
5,7/5/2013 9:36:06,D
6,7/5/2013 9:39:39,A
7,7/5/2013 9:40:28,B
8,8/5/2013 9:35:02,A
7,8/5/2013 9:35:08,A
8,8/5/2013 9:35:29,B
6,8/5/2013 9:36:39,B
I need to count how many times each day an event changed state as long as the time between states was less than 30 seconds over the time period.
Basically I am looking for the following result set
6/5/2013 | 1
7/5/2013 | 2
8/5/2013 | 1
I've tried several different types of queries, but nothing works. I am using SQL Server Reporting Services 2008.
declare #t table (ID int,[DateTime] datetime ,EventType varchar);
insert #t values
(1,'6/5/2013 9:35:00','B'),
(1,'6/5/2013 9:35:24','A'),
(2,'6/5/2013 9:35:36','B'),
(3,'6/5/2013 9:36:11','D'),
(2,'6/5/2013 9:39:16','A'),
(3,'6/5/2013 9:40:48','B'),
(4,'7/5/2013 9:35:19','B'),
(4,'7/5/2013 9:35:33','A'),
(5,'7/5/2013 9:35:53','B'),
(5,'7/5/2013 9:36:06','D'),
(6,'7/5/2013 9:39:39','A'),
(7,'7/5/2013 9:40:28','B'),
(8,'8/5/2013 9:35:02','A'),
(7,'8/5/2013 9:35:08','A'),
(8,'8/5/2013 9:35:29','B'),
(6,'8/5/2013 9:36:39','B');
--select * from #t order by ID, DateTime;
with cte as (
select *, cast([DateTime] as date) the_date, row_number() over (partition by ID order by DateTime) row_num
from #t
)
select c1.the_date, count(1)
from cte c1
join cte c2
on c2.ID = c1.ID
and c2.row_num = c1.row_num + 1
where datediff(S,c1.DateTime, c2.DateTime) < 30
group by c1.the_date
order by c1.the_date;
Try this:
select CONVERT(VARCHAR(10), a.DateTime, 103) [Date], count(a.ID) Count from Table a
inner join Table b on a.ID = b.ID
where DATEDIFF(second,a.DateTime,b.DateTime) between 1 and 29 and a.ID = b.ID
and Cast(a.DateTime as Date) = Cast(b.DateTime as date)
group by CONVERT(VARCHAR(10), a.DateTime, 103)

Exact Claim Count for each rows using pivot with join in SQL Server 2012

By executing the below SQL 2012 Query, I got the following output
declare
#ticketstatus nvarchar(20) = 'To Be Allocated'
SELECT m1.ClaimSource, m1.Insurance, n1.[Claim Count], n1.[Claim Value],
ISNULL(m1.[0-30],0) [0-30],
ISNULL(m1.[31-60],0) [31-60],
ISNULL(m1.[61-90],0) [61-90],
ISNULL(m1.[91-120],0) [91-120],
ISNULL(m1.[121-210],0) [121-210],
ISNULL(m1.[210++],0) [210++]
FROM (
SELECT *
FROM (
SELECT ClaimSource, Insurance, CurrentBalance _Count, AgeBucket
FROM ClaimMaster
) m
PIVOT (
COUNT(_Count)
FOR AgeBucket IN ([0-30],[31-60],[61-90],[91-120],[121-210],[210++])
) n
) m1
join
(SELECT Insurance, COUNT(Insurance) [Claim Count], SUM(CurrentBalance) [Claim Value] FROM ClaimMaster
WHERE (TicketStatus = #ticketstatus OR #ticketstatus IS NULL)
GROUP BY Insurance) n1
ON m1.Insurance = n1.Insurance
ORDER BY n1.[Claim Count] DESC
How can I get the correct output for Claim Count, Claim Value on the 4, 5 & 6 rows. Instead of showing full claim count, it should show the respective claim count filter by Claim Source such as Claim Count should be 2 and appropriate Claim Value.
Can anyone help me on this.
Add claimsource and join on that as well?
declare
#ticketstatus nvarchar(20) = 'To Be Allocated'
SELECT m1.ClaimSource, m1.Insurance, n1.[Claim Count], n1.[Claim Value],
ISNULL(m1.[0-30],0) [0-30],
ISNULL(m1.[31-60],0) [31-60],
ISNULL(m1.[61-90],0) [61-90],
ISNULL(m1.[91-120],0) [91-120],
ISNULL(m1.[121-210],0) [121-210],
ISNULL(m1.[210++],0) [210++]
FROM (
SELECT *
FROM (
SELECT ClaimSource, Insurance, CurrentBalance _Count, AgeBucket
FROM ClaimMaster
) m
PIVOT (
COUNT(_Count)
FOR AgeBucket IN ([0-30],[31-60],[61-90],[91-120],[121-210],[210++])
) n
) m1
join
(SELECT ClaimSource, Insurance, COUNT(Insurance) [Claim Count], SUM(CurrentBalance) [Claim Value] FROM ClaimMaster
WHERE (TicketStatus = #ticketstatus OR #ticketstatus IS NULL)
GROUP BY ClaimSource, Insurance) n1
ON m1.Insurance = n1.Insurance and m1.ClaimSource = n1.ClaimSource
ORDER BY n1.[Claim Count] DESC

Multiple value IF statement, to show in select

Any help appreciated,
the code below is from a database which someone made, every time a receipt is made a unique receipt id is issued. same when a reversal is made a new receipt is issued. what links the two are the pay in number. If a reverse is issued, the reverse flag changes on the old receipt to Y and the new one says N. i have my query that select Minimum date and Max data, for receipts returned will have a much later date that when it was first created. The issue is when there is no reverse, it still pulls information as the min and max date are the same. I am fully aware that i need an if statement, but have no idea how to do it since i am new to Databases.
Select distinct r.receipt_date, r.receipt_no, r.doc_no as Payin_No,r.trans_amt,l.location_desc, ct.charge_type_desc,
(select un.first_name + ' ' + un.last_name)as cashier,
r.payee, r.comments, r.reverse_flag, ret1.returned_by, ret1.return_date
from Cashier..receipts as r
inner join Cashier..location as l on r.location_id=l.location_id
inner join [Cashier].[dbo].[charge_type] as ct on ct.charge_type_no=r.charge_type_no
inner join Cashier..user_name as un on un.user_name=(UPPER(r.created_by))
inner join (
select receipt_no as Return_Receipt ,
(select un2.first_name + ' ' + un2.last_name) as returned_by,
created_date as return_date, doc_no as Payin_no,
r1.reverse_flag
from Cashier..receipts as r1
inner join Cashier..user_name as un2 on un2.user_name=(UPPER(r1.created_by))
where doc_no = r1.doc_no
and created_date = (select MAX(created_date)
from Cashier..receipts where doc_no = r1.doc_no)) as ret1
on (ret1.Payin_no=r.doc_no)
where r.receipt_date = (select MIN(r1.receipt_date) from Cashier..receipts as r1 where r1.receipt_no = r.receipt_no )
Issue i am having, the return by is the same as created
Desired result
Is this basically what you're trying to do?
-- test data creation, for me
create table receipts (receipt_no int, receipt_date datetime, doc_no int, reverse_flag char(1), returned_by varchar(10), create_date datetime, created_date datetime)
insert into receipts values (1, '1/1/2016', 12345, 'Y', 'John', null, '1/1/2016')
insert into receipts values (2, '2/15/2016', 12345, 'N', null, '2/15/2016', '2/15/2016')
SELECT r.receipt_date, r.receipt_no, r.doc_no, r.reverse_flag, ret1.return_date
FROM receipts r
INNER JOIN (
SELECT doc_no, create_date as return_date
FROM receipts
WHERE reverse_flag = 'N')ret1 on r.doc_no = ret1.doc_no and ret1.return_date > r.receipt_date
WHERE r.reverse_flag = 'Y' and r.doc_no = 12345
If that's your goal, I think you just tack this on to the very end of your query:
and r.receipt_date < ret1.return_date
Edit: Based on your update, I think tack this onto the end:
and convert(date, r.receipt_date) < convert(date, ret1.return_date)
I'm still really not sure what you want.
select *
from ( select doc_no, min(receipt_date) as min_receipt_date
from receipts group by doc_no ) as min_receipt
left outer join ( select doc_no, max(receipt_date) as max_receipt_date
from receipts group by doc_no) as max_receipt
on min_receipt.doc_no = max_receipt.doc_no and
min_receipt.min_receipt_date <> max_receipt.max_receipt_date
for
insert into receipts values (1, '2016-01-01', 12345, 'Y', 'John', null, '2016-01-01');
insert into receipts values (2, '2016-03-15', 12345, 'N', null, '2016-03-15', '2016-03-15');
insert into receipts values (3, '2016-03-15', 123667, 'N', null, '2016-03-15', '2016-03-15');
yields
doc_no min_receipt_date doc_no max_receipt_date
12345 January, 01 2016 00:00:00 12345 March, 15 2016 00:00:00
123667 March, 15 2016 00:00:00 (null) (null)
but it assumes that the return date will never be the same as the original receipt date. I also left off the Y and N flags because I don't see how it's necessary if the min date is always the original purchase date. The other answer here uses the created_date but in your screenshot of the table data, you only show one date so I wrote it assuming only one date (the receipt date). I tested that on MySQL because SQLFiddle was hating on my SQL Server syntax for inserts and I don't have another way to test right now.
This is what i was looking for, figured it out. Thank you Max for opening insights on how i could tackle the problem.
Select distinct r.receipt_date, r.receipt_no, r.doc_no as Payin_No,r.trans_amt,l.location_desc, ct.charge_type_desc,
(select un.first_name + ' ' + un.last_name)as cashier,
r.payee, r.comments, r.cost_centre, r.item, r.programme, r.activity, r.btl_sof, r.reverse_flag, --, ret1.returned_by, ret1.return_date
(case when r.reverse_flag = 'Y' then (select (un2.first_name + ' ' + un2.last_name)from Cashier..receipts as r1
inner join Cashier..user_name as un2 on un2.user_name=(UPPER(r1.created_by)) where created_date = (select MAX(created_date)
from Cashier..receipts where doc_no = r.doc_no)) end ) as returned_by ,
(case when r.reverse_flag = 'Y' then (select created_date from Cashier..receipts as r1
inner join Cashier..user_name as un2 on un2.user_name=(UPPER(r1.created_by)) where created_date = (select MAX(created_date)
from Cashier..receipts where doc_no = r.doc_no)) end ) as returned_date
from Cashier..receipts as r
inner join Cashier..location as l on r.location_id=l.location_id
inner join [Cashier].[dbo].[charge_type] as ct on ct.charge_type_no=r.charge_type_no
inner join Cashier..user_name as un on un.user_name=(UPPER(r.created_by))
where r.receipt_date = (select MIN(r1.receipt_date) from Cashier..receipts as r1 where r1.receipt_no = r.receipt_no )

Resources