can not make a select with the desired values in SQL Server - sql

Creating the table
CREATE TABLE dbo.factura
(
customer_code varchar(20),
invoice_number char(4),
line_number char(2),
data date
);
DROP TABLE dbo.factura;
SELECT * FROM dbo.factura;
Populating the table:
INSERT INTO dbo.factura VALUES ('ABC', '0012', '01', '2020-10-01');
INSERT INTO dbo.factura VALUES ('ABC', '0012', '02', '2020-11-01');
INSERT INTO dbo.factura VALUES ('ABC', '0012', '03', '2020-11-01');
INSERT INTO dbo.factura VALUES ('ABC', '0013', '08', '2021-01-21');
INSERT INTO dbo.factura VALUES ('ABC', '0013', '09', '2020-09-01');
INSERT INTO dbo.factura VALUES ('SLIK', '0001', '01', '2021-01-01');
INSERT INTO dbo.factura VALUES ('SLIK', '0001', '02', '2020-02-01');
Write a SQL statement to return the recordset:
CUSTOMER_CODE, INVOICE_NR, LINE_NR
where NR_LINE is the line number with the most recent value in the DATA column for each invoice of each customer in the table.
I tried to do with a self join, but it doesn't work.
Do you have any ideas how to write this query?

If you want the rows by sorted by line_number in descending order then the query will be:
with cte as (
select CUSTOMER_CODE, INVOICE_number, LINE_number , row_number()over(partition by customer_code,invoice_number order by LINE_number desc) rn
from factura
)
select CUSTOMER_CODE, INVOICE_number, LINE_number from cte where rn=1
Output:
If you want the result in descending order of data field then the query will be:
with cte as (
select CUSTOMER_CODE, INVOICE_number, LINE_number , row_number()over(partition by customer_code,invoice_number order by data desc) rn
from factura
)
select CUSTOMER_CODE, INVOICE_number, LINE_number from cte where rn=1
Output:

Related

Spark SQL Query to assign join date by next closest once

`CREATE TABLE TABLE_1(
CALL_ID INT,
CALL_DATE DATE);
INSERT INTO TABLE_1(CALL_ID, CALL_DATE)
VALUES (1, '2022-10-22'),
(2, '2022-10-31'),
(3, '2022-11-04');
CREATE TABLE TABLE_2(
PROD_ID INT,
PROD_DATE DATE);
INSERT INTO TABLE_2(PROD_ID, PROD_DATE)
VALUES (1, '2022-10-25'),
(2, '2022-11-17');
CREATE TABLE TABLE_RESULT(
CALL_ID INT,
CALL_DATE DATE,
PROD_ID INT,
PROD_DATE DATE);
INSERT INTO TABLE_RESULT(CALL_ID, CALL_DATE, PROD_ID, PROD_DATE)
VALUES (1, '2022-10-22', 1, '2022-10-25'),
(2, '2022-10-31', NULL, NULL),
(3, '2022-11-04', 2, '2022-11-17');`
Can you help me to create the TABLE_RESULT with a join in a elegant way? This is a very small example.
Thanks
I solved it. Thanks anyway.
SELECT * FROM (SELECT *, COALESCE(LEAD(CALL_DATE) OVER (PARTITION BY 1 ORDER BY CALL_DATE), CURRENT_DATE) AS CALL_DATE_NEXT FROM TABLE_1) AS A LEFT JOIN TABLE_2 AS B ON (A.CALL_DATE<=B.PROD_DATE AND A.CALL_DATE_NEXT>B.PROD_DATE)

Convert rows to columns using pivot

I try to convert this procedure to PIVOT, but I can't. Does anyone have a solution to help?
I have a table has ItemID, StoreID,Stock
I want to convert it to ItemID, Store1,Store2,Store3...,Stock
sum the stock according to itemID and StoreID then inserts the result as a row.
Many thanks
CREATE table #test222
([Id] int,[ItemID] INT, [storeid] int, [stock] decimal(18,2)
);
INSERT INTO #test222
([Id],[ItemID], [storeid], [stock])
VALUES
(1, 1, 3,10),
(2, 1,1, 20),
(3, 1,1, 30),
(4, 2,1, 40),
(5, 2,2,50),
(6, 2,2,60),
(7, 3,2,70),
(8, 4,2,80),
(9, 4,2,90),
(10, 5,2,100);
select * from #test222;
select ItemID, store1,store2,storeid3,storeid4,storeid5,storeid6,storeid7,storeid8,storeid9,storeid10 stock
from
(
select ItemID, storeid, stock
from #test222
) d
pivot
(
max(stock)
for storeid in (1,2,3,4,5,6,7,8,9,10)
) piv;
Give error:
Msg 102 Level 15 State 1 Line 9
Incorrect syntax near '1'.
Here is a simple PIVOT. Just remember to "feed" your pivot with just only the required columns
Example
Select *
From (
Select ItemID
,Col = 'store'+left(storeid,10)
,val = stock
From #test222
) src
Pivot ( max(val) for Col in ( store1,store2,storeid3,storeid4,storeid5,storeid6,storeid7,storeid8,storeid9,storeid10 ) ) src
Results

Select last row where given value changed

I want to select last row (by mod_date) where column new_status is different from previous entry for given object_id.
At first I tried with row_number but not made it, later I came up with lead/lag functions and I think I'm closer to solution but still not ideal results.
Here's the code and the fiddle:
https://www.db-fiddle.com/f/kS8SAi2WsAjfFLomd7t2it/0
CREATE TABLE changes
(object_id integer,
new_status smallint,
comment text,
mod_date timestamp);
INSERT INTO changes
VALUES
(1001, 0, null, '2020-06-01 12:01'),
(1001, 1, 'XYZ', '2020-06-01 12:05'),
(1001, 1, 'YZX', '2020-06-01 12:11'),
(1002, 1, 'XYZ', '2020-06-01 13:21'),
(1002, 1, 'AAA', '2020-06-01 13:25'),
(1002, 0, 'BCA', '2020-06-01 14:11'),
(1003, 1, 'AXX', '2020-06-01 14:12'),
(1003, 0, 'YZX', '2020-06-01 14:13'),
(1003, 0, 'YYY', '2020-06-01 14:17');
SELECT object_id, min(mod_date), new_status FROM (
SELECT
object_id
, mod_date
, new_status
--, row_number() over (partition BY object_id ORDER BY mod_date desc) rn
, lag(new_status) OVER (partition by object_id ORDER BY mod_date desc) as next_status
FROM changes
ORDER BY 1)x
WHERE new_status = next_status
OR next_status is null
GROUP BY 1,3
The output for 1001, and 1003 is fine, for 1002 it should be row with status 0.
Appreciate any help and suggestions!
I think you want:
select distinct on (object_id) c.*
from (select c.*,
lag(new_status) over (partition by object_id order by mod_date) as prev_ns
from changes c
) c
where prev_ns is distinct from new_status
order by object_id, mod_date desc;
Here is a db<>fiddle.

SQL use count or sum for specific result

I was trying to get result with native SQL query as it is presented on below picture, currently im not sure if there is any way to get this result with using only SQL.
I was around this query, but no idea currently further:
SELECT
receipts.client_code clientCode,
date_trunc('MON', receipts.create_date) monthYear,
COUNT(date_trunc('MON', receipts.create_date)) receipts,
subReceipts.total total
FROM receipts
LEFT JOIN (SELECT
receipts.client_code clientCode,
date_trunc('MON', receipts.create_date) monthYear,
COUNT(date_trunc('MON', receipts.create_date)) total
FROM receipts
GROUP BY
receipts.client_code,
date_trunc('MON' ,receipts.create_date)
ORDER BY
date_trunc('MON' ,receipts.create_date)
) subReceipts ON subReceipts.clientCode = receipts.client_code
GROUP BY
receipts.client_code,
date_trunc('MON' ,receipts.create_date),
subReceipts.total
ORDER BY
date_trunc('MON' ,receipts.create_date)
Sample sql data and db table create script:
CREATE TABLE receipts
(
receipt_id int primary key,
client_code varchar not null,
create_date date not null
);
insert into receipts (receipt_id, client_code, create_date) values (1, 'fx90', to_date('2016/01/11', 'yyyy/MM/dd'));
insert into receipts (receipt_id, client_code, create_date) values (2, 'fx90', to_date('2016/02/12', 'yyyy/MM/dd'));
insert into receipts (receipt_id, client_code, create_date) values (3, 'fx90', to_date('2016/02/20', 'yyyy/MM/dd'));
insert into receipts (receipt_id, client_code, create_date) values (4, 'fx90', to_date('2016/03/11', 'yyyy/MM/dd'));
insert into receipts (receipt_id, client_code, create_date) values (5, 'fx90', to_date('2016/03/12', 'yyyy/MM/dd'));
insert into receipts (receipt_id, client_code, create_date) values (6, 'fx90', to_date('2016/03/19', 'yyyy/MM/dd'));
Example result
Assuming mysql, you could just do:
set #running_total := 0;
SELECT
client_code,
CONCAT(MONTH(create_date), ' - ', YEAR(create_date)) as month_year,
COUNT(receipt_id) AS receipts_month,
(#running_total := #running_total + COUNT(receipt_id)) as total_receipts
FROM receipts
GROUP BY client_code, MONTH(create_date), YEAR(create_date)
ORDER BY receipt_id;
For postgresql:
SELECT clientCode, monthYear, receipts,
sum(receipts) over(order by monthYear) as total
FROM (
SELECT receipts.client_code clientCode,
date_trunc('MON', receipts.create_date) monthYear,
COUNT(1) receipts
FROM receipts
GROUP BY receipts.client_code, monthYear
) X
ORDER BY monthYear

How to retrieve WTD,YTD,MTD users from a user traffic table in the same query?

In a user traffic table as below, I would like to compute the week to date (WTD), month to date ( MTD ), year to date ( YTD ) user and returned user counts.
Test data :
create table user_traffic (session_id number(6), session_day date,
user_id number(6), product_id number(6));
insert into user_traffic values ( 1, date '2016-09-07', 101, 1);
insert into user_traffic values ( 2, date '2016-09-07', 101, 4);
insert into user_traffic values ( 3, date '2016-09-07', 102, 1);
insert into user_traffic values ( 4, date '2016-09-08', 101, 2);
insert into user_traffic values ( 5, date '2016-09-08', 101, 4);
insert into user_traffic values ( 6, date '2016-09-09', 102, 1);
insert into user_traffic values ( 7, date '2016-09-10', 102, 1);
insert into user_traffic values ( 8, date '2016-09-10', 103, 3);
insert into user_traffic values ( 9, date '2016-09-25', 104, 3);
insert into user_traffic values ( 10, date '2016-10-01', 103, 1);
insert into user_traffic values ( 11, date '2016-10-02', 104, 3);
Expected Output :-
Week_Start_Day, WTD_new_cnt, WTD_returned_cnt
Month_Start_Day, MTD_new_cnt, MTD_returned_cnt
Year_Start_Day, YTD_new_cnt, YTD_returned_cnt
Comments :-
For eg: In the above user traffic table userid=104 visited on Oct 02nd and the WTD,MTD,YTD new/returned counts would be as below.
WTD,new,return
2016-09-26(Mon)(Week start day ), 1,0 ( For userid = 104 )
MTD,new,return
2016-09,1,1
2016-10,0,1
YTD,new,return
2016,0,1
What I have tried?
select session_day,
COUNT( distinct user_id ) AS user_cnt,
count(distinct user_id) - lag(count(distinct user_id))
over (order by session_day) gain,
count(newu) AS newu, count(returnu) AS returnu
from
(
select session_id,
session_day,
user_id,
CASE WHEN
count(*) over ( partition by user_id ORDER BY
session_day,session_id ROWS
BETWEEN UNBOUNDED PRECEDING AND
CURRENT ROW
)
= 1
THEN 1
END
AS newu,
CASE WHEN
lag( session_day,1 ) over ( partition by user_id ORDER
BY session_day,session_id
)
<>
lag( session_day,1 ) over ( order by
session_day,session_id
)
THEN 1
END AS returnu
from user_traffic u
)
group by session_day
order by session_day;
I have built this sql in computing the new/returned users from the user traffic table at sessionday level.