SQL PIVOT Date as day not coming in proper order - sql

I am trying to get records from previous month's last day to current month's last day with below code
SELECT [DAY],
[N-1 HSD],
[N-2 HSD],
[N-6 HSD],
DIP,
[STOCK LTR],
[PURRCHASE LTR],
[STOCK LTR] + [PURRCHASE LTR] AS [Total Ltr],
Isnull([TESTING], 0) AS Testing,
0 AS [Sales As Reading],
0 AS [Sales As Dip],
0 AS [Diff Ltr],
(SELECT TOP (1) _RATE
FROM _PRODUCTRATE
WHERE _ISDELETED = N'1'
AND _PRODUCTID_PK = N'154eeb16-0c5c-44e4-b5cc-b0f30a22098f'
AND _DATE <= _RATEDATE
ORDER BY _DATE DESC) AS [Rate Rs],
0 AS [Amount Rs]
FROM
(SELECT TOP (100) PERCENT Day(DBO._DSRENTRY._DSRENTRYDATE) AS [Day],
DBO._DSRENTRYDET._CLOSING,
DBO._DSRENTRY._DIPSCALE AS DIP,
DBO._DSRENTRY._DIP AS [Stock Ltr],
DBO._DSRENTRY._TESTINGQTY AS [Testing],
DBO._NOZZLE._NOZZLENAME,
(SELECT Isnull(Sum(_QTY), 0) AS Expr1
FROM DBO._TANKVACCANT
WHERE (_ISDELETED = N'1')
AND (_TANKID_PK = N'88e31d8c-acf5-4c09-a91f-28577c66d070')
AND (_TANKVACCANTDATE = _DSRENTRYDATE)
AND (_COMPANYID_PK = N'747c28ad-2924-4456-91fe-6f4f7b0db3fd')
AND (_WORKGROUPNAME = N'SRV')) AS [Purrchase Ltr],
DBO._DSRENTRY._DSRENTRYDATE AS _RATEDATE
FROM DBO._NOZZLE
RIGHT OUTER JOIN DBO._DSRENTRYDET ON DBO._NOZZLE._NOZZLEID_PK = DBO._DSRENTRYDET._NOZZLEID_PK
RIGHT OUTER JOIN DBO._DSRENTRY ON DBO._DSRENTRYDET._DSRENTRYID_PK = DBO._DSRENTRY._DSRENTRYID_PK
WHERE (DBO._DSRENTRYDET._ISDELETED = N'1')
AND (DBO._DSRENTRY._COMPANYID_PK = N'747c28ad-2924-4456-91fe-6f4f7b0db3fd')
AND (DBO._DSRENTRYDET._COMPANYID_PK = N'747c28ad-2924-4456-91fe-6f4f7b0db3fd')
AND (DBO._NOZZLE._COMPANYID_PK = N'747c28ad-2924-4456-91fe-6f4f7b0db3fd')
AND (DBO._DSRENTRY._WORKGROUPNAME = N'SRV')
AND (DBO._DSRENTRYDET._WORKGROUPNAME = N'SRV')
AND (DBO._NOZZLE._WORKGROUPNAME = N'SRV')
AND (DBO._DSRENTRY._ISDELETED = N'1')
AND (DBO._NOZZLE._ISDELETED = N'1')
AND (DBO._DSRENTRY._DSRENTRYDATE >= CONVERT(DATETIME, '31.08.2017 00:00:00', 105))
AND (DBO._DSRENTRY._DSRENTRYDATE <= CONVERT(DATETIME, '30.09.2017 23:59:59', 105))
AND (DBO._DSRENTRY._TANKID_PK = N'88e31d8c-acf5-4c09-a91f-28577c66d070')
ORDER BY DBO._DSRENTRY._DSRENTRYDATE) AS DERIVEDTBL_1 PIVOT(Sum(_CLOSING)
FOR _NOZZLENAME IN ([N-1 HSD], [N-2 HSD], [N-6 HSD])) AS PVTTABLE
below is the output
DAY N-1 HSD N-2 HSD N-6 HSD DIP STOCK LTR PURRCHASE LTR Total Ltr Testing Sales As Reading Sales As Dip Diff Ltr Rate Rs Amount Rs
1 1886247.00 1139460.00 391836.00 140.00 15319.00 0.00 15319.00 10.00 0 0 0 59.86 0
.........
.........
.........
29 1909720.00 1147850.00 397467.00 102.40 10473.00 0.00 10473.00 10.00 0 0 0 61.57 0
30 1910934.00 1148180.00 397467.00 90.60 8932.00 6000.00 14932.00 10.00 0 0 0 61.65 0
31 1885620.00 1139191.00 391788.00 70.00 6310.00 10000.00 16310.00 10.00 0 0 0 59.78 0
As showing in output the last recod which is 31 1885620.00 1139191.00 391788.00 70.00 6310.00 10000.00 16310.00 10.00 0 0 0 59.78 0 is showing into bottom but this should be first,
If I changed Day(DBO._DSRENTRY._DSRENTRYDATE) to DBO._DSRENTRY._DSRENTRYDATE then records are comming in proper order but its giving me full date and time.
like below
DAY N-1 HSD N-2 HSD N-6 HSD DIP STOCK LTR PURRCHASE LTR Total Ltr Testing Sales As Reading Sales As Dip Diff Ltr Rate Rs Amount Rs
2017-08-31 00:00:00.000 1885620.00 1139191.00 391788.00 70.00 6310.00 10000.00 16310.00 10.00 0 0 0 59.78 0
2017-09-01 00:00:00.000 1886247.00 1139460.00 391836.00 140.00 15319.00 0.00 15319.00 10.00 0 0 0 59.86 0
2017-09-02 00:00:00.000 1887258.00 1139601.00 391938.00 130.00 14062.00 0.00 14062.00 10.00 0 0 0 59.94 0
----------------------------
----------------------------
2017-09-29 00:00:00.000 1909720.00 1147850.00 397467.00 102.40 10473.00 0.00 10473.00 10.00 0 0 0 61.57 0
2017-09-30 00:00:00.000 1910934.00 1148180.00 397467.00 90.60 8932.00 6000.00 14932.00 10.00 0 0 0 61.65 0
But I need only day not full datetime,
How I archived this.

Using DATEPART(DAY, [Day])helps to order your output. Please add it in the select clause and order by the same column to get the sorted output.

Related

SQL - Building iteration table

I have a problem with table's iteration. There is status product (test_product) in stock and actions: add or remove from stock.
product
action
operation_date
number
total
test_product
add
2023-01-03
4
4
test_product
remove
2023-01-05
-3
1
test_product
remove
2023-01-07
-1
0
In some day we have add or remove product, number of product and total number.
I want to count number of days, where total number is 0 in some period, let's say from 2023-01-01 to 2023-01-10 with starting value of total column is 0.
In my mind I have table like this:
calendar_day
product
action
operation_day
number
total
2023-01-01
0
2023-01-02
0
2023-01-03
test_product
add
2023-01-03
4
4
2023-01-04
4
2023-01-05
test_product
remove
2023-01-05
-3
1
2023-01-06
1
2023-01-07
test_product
remove
2023-01-07
-1
0
2023-01-08
0
2023-01-09
0
2023-01-10
0
Counting of 0 days is technical operation, it's not important now. Problem is building table.
I've tried something like this:
GO
DECLARE #PRODUCT AS VARCHAR(30)
SET #PRODUCT = 'test_product'
DECLARE #TOTAL AS INT
SET #TOTAL = 0
DECLARE #STOP_DATE AS DATE;
SET #STOP_DATE = CAST('2023-01-10' AS DATE)
DECLARE #UP_DATE AS DATE;
SET #UP_DATE = CAST('2023-01-01' AS DATE);
WHILE #STOP_DATE >= #UP_DATE
BEGIN
SELECT
#UP_DATE AS calendar_day,
CASE
WHEN operation_date = #UP_DATE THEN operation_date
ELSE ''
END AS operation_date,
number,
#TOTAL+number AS total
FROM stock
JOIN products ON products.id = stock.product_id
WHERE products.name = #PRODUCT
AND stock.operation_date >= #UP_DATE
AND stock.operation_date <= #UP_DATE
SET #UP_DATE = DATEADD(DAY, 1, #UP_DATE)
END
But I've got separation result, 7 of them are empty and it's too slow, because we have 9000 items for now.
Can you help me?
You can accomplish to this task into three steps:
build a calendar table with a recursive query, that stops at calen_date < '2023-10-01'
left join the calendar table with your products table
compute a running sum on your number value to get your total.
WITH calendar AS (
SELECT CAST('2023-01-01' AS DATE) AS calendar_day
UNION ALL
SELECT DATEADD(DAY, 1, calendar_day) FROM calendar WHERE calendar_day < '2023-01-10'
)
SELECT calendar_day, product, action_, operation_date, number,
SUM(COALESCE(number,0)) OVER(ORDER BY calendar_day) AS total
FROM calendar c
LEFT JOIN test_product p
ON c.calendar_day = p.operation_date
Output:
calendar_day
product
action
operation_day
number
total
2023-01-01
0
2023-01-02
0
2023-01-03
test_product
add
2023-01-03
4
4
2023-01-04
4
2023-01-05
test_product
remove
2023-01-05
-3
1
2023-01-06
1
2023-01-07
test_product
remove
2023-01-07
-1
0
2023-01-08
0
2023-01-09
0
2023-01-10
0
Check the demo here.

Left Outer Join SSMS

I am attempting to left outer join between two tables.
select id, startdate, name, code, email from edw.dbo.starts
id startdate name code email yearfiled
15 2/4/2018 SO 1083 sql#gmail.com 2018
17 3/4/2018 SO 1083 ssms#gmail.com 2018
19 4/4/2018 SO 1083 ssrs#gmail.com 2018
21 5/4/2018 SO 1083 ssas#gmail.com 2018
21 5/5/2017 SO 1083 who#gmail.com 2017
select customer, return_year, revenue, code from sql.dbo.paid
customer return_year revenue code
15 2018 15.00 1083
17 2018 25.00 1083
21 2018 35.00 1083
21 2017 35.00 1083
select
month(os.startdate) as startmonth
,os.name
,os.code
,coalesce(s.revenue, 0) as revenue
,count(os.email) as commission
from
edw.dbo.starts as os
left outer join
sql.dbo.paid as s
on
os.id = s.customer
and os.yearfile = s.return_year
where
os.yearfiled = 2018
and os.code = '1083'
and os.startdate is not null
group by
month(os.startdate)
,os.name
,os.code
,coalesce(s.revenue, 0);
startmonth name code revenue commission
2 SO 1083 15.00 1
3 SO 1083 25.00 1
4 SO 1083 0.00 1
5 SO 1083 0.00 1
The issue:
Customer = 21 from sql.dbo.paid shows zero for the revenue in the joined query even though it had a reported $35.00 revenue in the table.
Requested:
startmonth name code revenue commission
2 SO 1083 15.00 1
3 SO 1083 25.00 1
4 SO 1083 0.00 1
5 SO 1083 35.00 1
Please try this one.
create table starts
(id int ,
startdate date ,
name varchar(10),
code int ,
email varchar(20),
yearfiled int )
create table paid
( customer int ,
return_year int ,
revenue decimal(10,2),
code int)
insert into starts values
(15,'2/4/2018','SO',1083,'sql#gmail.com',2018),
(17,'3/4/2018','SO',1083,'ssms#gmail.com',2018),
(19,'4/4/2018','SO',1083,'ssrs#gmail.com',2018),
(21,'5/4/2018','SO',1083,'ssas#gmail.com',2018),
(21,'5/5/2017','SO',1083,'who#gmail.com',2017)
insert into paid values
(15,2018,15.00,1083),
(17,2018,25.00,1083),
(21,2018,35.00,1083),
(21,2017,35.00,1083)
select month(a.startdate)as startmonth,a.name,a.code,
case when b.revenue is null then 0 else b.revenue end as revenue,
count(a.email) as commission
from starts a
left join paid b on a.yearfiled=b.return_year and a.id=b.customer
where a.yearfiled=2018 and a.code=1083
group by month(a.startdate),a.name,a.code,b.revenue
/*
startmonth name code revenue commission
----------- ---------- ----------- --------------------------------------- -----------
2 SO 1083 15.00 1
3 SO 1083 25.00 1
4 SO 1083 0.00 1
5 SO 1083 35.00 1
*/

SQL Query to extract Average Quantity

I want to calculate the average quantity customer purchases in one basket
(Where 1 Basket = Multitple purchases in 1 day)
from the table transaction and update it into cust360.average_basket_Qty
Transactions:-
Trasactions_ID cust_id Tran_date Qty Total_amt
80712190438 270351 2014-02-28 00:00:00.000 5 4265.3
29258453508 270384 2014-02-27 00:00:00.000 5 8270.925
51750724947 273420 2014-02-24 00:00:00.000 2 1748.11
93274880719 271509 2014-02-24 00:00:00.000 3 4518.345
51750724947 273420 2014-02-23 00:00:00.000 2 1748.11
97439039119 272357 2014-02-23 00:00:00.000 2 1821.04
45649838090 273667 2014-02-22 00:00:00.000 1 1602.25
Cust360 Table: -
Cust_id Gender Age Basket_count Total_sale Date Average_basket_Qty
266783 M 525 0 3113 2013-02-20 NULL
266784 F 314 1 5694 2012-12-04 NULL
266785 F 392 0 21613 2013-08-01 NULL
266788 F 551 0 6092 2013-02-12 NULL
266794 F 564 1 27981 2014-02-12 NULL
Following query should work for you
UPDATE DEST
SET DEST.Average_basket_Qty = SRC.AVG_QTY
FROM Cust360 DEST
INNER JOIN
(
SELECT CUST_ID, CAST(TRAN_DATE AS DATE), AVG(QTY) AVG_QTY
FROM Transactions
GROUP BY CUST_ID,CAST(TRAN_DATE AS DATE)
) SRC ON SRC.CUST_ID=DEST.Cust_id

Teradata SQL: Search for the first time a value changes in a column

So, I have a table that tracks customer accounts on a daily basis and records values for each business day, such as the balance on that account.
For example:
Acct_Nbr Acct_Open_Date System_Date Balance
-------------------------------------------------
111 2017-12-01 2017-12-01 0.00
111 2017-12-01 2017-12-04 0.00
111 2017-12-01 2017-12-05 0.00
111 2017-12-01 2017-12-06 500.00
222 2017-12-01 2017-12-01 0.00
222 2017-12-01 2017-12-04 0.00
222 2017-12-01 2017-12-05 0.00
222 2017-12-01 2017-12-06 0.00
222 2017-12-01 2017-12-07 0.00
222 2017-12-01 2017-12-08 250.00
I'm trying to write a query that will return the # of days between Acct_Open_Date and the System_Date on which the Balance first became > 0 (i.e. the date the account got funded).
I plan on grouping the # of days in buckets, using a case when statement (i.e. <=5 days, 6-10 days, etc.) and for each bucket return the # of accounts.
Based on the table above, it would return:
Time_to_fund Count_of_accts
-----------------------------
<=5 days 1
6-10 days 1
>10 days 0
I'm not entirely sure how to write a query that will search on a per account basis through each row until it finds a value for Balance > 0, and then takes the System_Date for that row and subtracts the Acct_Open_Date from that to give me # of days.
Any help would be appreciated. Thanks!
select
CASE WHEN diff <= 5 THEN'<=5 days'
when diff <= 10 then '6-10 days'
ELSE '>10 days'
END as Time_to_fund,
COUNT(*)
from
(
select
System_Date - Acct_Open_Date as diff -- number of days between
from mytable
where Balance > 0
qualify -- find the first row with a Balance > 5
row_number()
over (partition by Acct_Nbr
order by System_Date) = 1
) as dt
Try using a GROUP BY within a GROUP BY:
SELECT CASE WHEN fund_times.Time_to_fund_in_days<= 5 THEN'<=5 days'
when fund_times.Time_to_fund_in_days<= 10 then '6-10 days'
ELSE '>10 days' END as Time_to_fund, COUNT(fund_times.acct_Number) AS Count_of_accts
(SELECT t.acct_Number, MIN( (t.System_Date - t.Acct_Open_Date) * 86400) as Time_to_fund_in_days
from table as T
WHERE t.Balance>0
GROUP BY t.acct_Number) AS fund_times
GROUP BY CASE WHEN fund_times.Time_to_fund_in_days<= 5 THEN'<=5 days'
when fund_times.Time_to_fund_in_days<= 10 then '6-10 days'
ELSE '>10 days' END

SQL Case Statement with SUM Group

I know there must be some question like me. Seems I cannot find the question, I sorry to ask this question.
Below is my table (SalesTransaction)
ID |SalesID |Amount |AmountReceived |OutStanding |Paid
2041 1000 600000 600000 0 1
2042 1000 1500000 2000000 -500000 1
2043 1000 900000 0 900000 0
2047 1002 300000 0 300000 0
Using SQL Query below:
SELECT ID,
SalesID,
Amount,
AmountReceived,
OutStanding,
Paid,
(CASE
WHEN Paid = 0 THEN (SELECT SUM(OutStanding)
FROM SalesTransaction
WHERE Paid = 1 )
ELSE 0 END) AS BalanceLastSchedule
FROM dbo.SalesTransaction
GROUP BY ID, SalesID, Amount, AmountReceived, OutStanding, Paid
I get result like below:
ID |SalesID |Amount |AmountReceived |OutStanding |Paid |BalanceLastSch
2041 1000 600000 600000 0 1 0.00
2042 1000 1500000 2000000 -500000 1 0.00
2043 1000 900000 0 900000 0 -500000
2047 1002 300000 0 300000 0 -500000
What I want to get like below:
ID |SalesID |Amount |AmountReceived |OutStanding |Paid |BalanceLastSch
2041 1000 600000 600000 0 1 0.00
2042 1000 1500000 2000000 -500000 1 0.00
2043 1000 900000 0 900000 0 -500000
2047 1002 300000 0 300000 0 0.00
Appreciate I get help on this. Thanks.
You are getting the wrong answer because you have not joined the Inner Query to find the sum with the SalesId. try this below script
SELECT
SeqNo,
SalesID,
Amount,
AmountReceived,
OutStanding,
Paid,
ISNULL((CASE
WHEN Paid = 0 THEN (SELECT SUM(OutStanding)
FROM SalesTransaction
WHERE Paid = 1
AND SalesId = T.SalesId)
ELSE 0 END),0.00) AS BalanceLastSchedule
FROM SalesTransaction T;
i just added the below setion inside tour inner query and removed the group By Clause
AND SalesId = T.SalesId