How sort data when use row_number() function? - sql

I want to sort data when using the row_number() function or other way around.
I sort new "sort_type column" when "e_type column" changed last status (when s_type <> e_type).
Raw data:
req_no | seq | s_date | e_date | s_type | e_type |
---------+-------+------------+------------+-----------+----------+
001 | 1 | 2017-01-01 | 2017-01-02 | 01 | 01 |
001 | 2 | 2017-01-02 | 2017-01-02 | 01 | 02 |
001 | 3 | 2017-01-02 | 2017-01-02 | 02 | 02 |
001 | 4 | 2017-01-02 | 2017-01-02 | 02 | 01 |
001 | 5 | 2017-01-02 | 2017-01-02 | 01 | 01 |
001 | 6 | 2017-01-02 | 2017-01-02 | 01 | 01 |
001 | 14 | 2017-01-03 | 2017-01-03 | 04 | 03 |
001 | 15 | 2017-01-03 | 2017-01-03 | 03 | 03 |
001 | 16 | 2017-01-03 | 2017-01-03 | 03 | 03 |
001 | 17 | 2017-01-03 | 2017-01-03 | 03 | 03 |
I get this result from my query right now:
req_no | seq | s_date | e_date | s_type | e_type | sort_type
-------+------+------------+------------+--------+--------+----------
001 | 1 | 2017-01-01 | 2017-01-02 | 01 | 01 | 1
001 | 2 | 2017-01-02 | 2017-01-02 | 01 | 02 | 1
001 | 3 | 2017-01-02 | 2017-01-02 | 02 | 02 | 2
001 | 4 | 2017-01-02 | 2017-01-02 | 02 | 01 | 2
001 | 5 | 2017-01-02 | 2017-01-02 | 01 | 01 | 3
001 | 6 | 2017-01-02 | 2017-01-02 | 01 | 01 | 4
001 | 14 | 2017-01-03 | 2017-01-03 | 04 | 03 | 1
001 | 15 | 2017-01-03 | 2017-01-03 | 03 | 03 | 2
001 | 16 | 2017-01-03 | 2017-01-03 | 03 | 03 | 3
001 | 17 | 2017-01-03 | 2017-01-03 | 03 | 03 | 4
But I want the result to be like this:
req_no | seq | s_date | e_date | s_type | e_type | sort_type
-------+------+------------+------------+--------+--------+----------
001 | 1 | 2017-01-01 | 2017-01-02 | 01 | 01 | 1
001 | 2 | 2017-01-02 | 2017-01-02 | 01 | 02 | 1
001 | 3 | 2017-01-02 | 2017-01-02 | 02 | 02 | 2
001 | 4 | 2017-01-02 | 2017-01-02 | 02 | 01 | 2
001 | 5 | 2017-01-02 | 2017-01-02 | 01 | 01 | 3 (or not show)
001 | 6 | 2017-01-02 | 2017-01-02 | 01 | 01 | 4 (or not show)
001 | 14 | 2017-01-03 | 2017-01-03 | 04 | 03 | 5 (or 3)
001 | 15 | 2017-01-03 | 2017-01-03 | 03 | 03 | 6 (or not show)
001 | 16 | 2017-01-03 | 2017-01-03 | 03 | 03 | 7 (or not show)
001 | 17 | 2017-01-03 | 2017-01-03 | 03 | 03 | 8 (or not show)
002 | 1 | 2017-01-05 | 2017-01-05 | 01 | 02 | 1
002 | 2 | 2017-01-05 | 2017-01-05 | 03 | 03 | 2
002 | 3 | 2017-01-05 | 2017-01-05 | 03 | 03 | 2
002 | 4 | 2017-01-05 | 2017-01-05 | 03 | 04 | 2
002 | 5 | 2017-01-05 | 2017-01-05 | 04 | 04 | 3 (or not show)
This is my SQL Server query:
SELECT
a.*,
ROW_NUMBER() OVER (PARTITION BY e_type ORDER BY req_no, seq) AS sort_type
FROM
tb_listtype a
Please help me. Thanks in advance ;)

Maybe help WITH
Try this
;With mytmpTable as
(
SELECT
a.*,
ROW_NUMBER() OVER (PARTITION BY e_type ORDER BY req_no, seq) AS sort_type
FROM
tb_listtype a
)
select * from mytmpTable where e_type=3 and sort_type>3

Try this:
select req_no, seq, s_date, e_date, s_type, e_type,
sort_type - sort_type_temp [sort_type]
from (
select req_no, seq, s_date, e_date, s_type, e_type,
sum(sort_type) over (partition by req_no order by s_date rows between unbounded preceding and current row) sort_type,
case when s_type <> e_type then -1 else 0 end sort_type_temp
from (
select req_no, seq, s_date, e_date, s_type, e_type,
case when s_type <> e_type then 1 else 0 end sort_type
from MY_TABLE
) a
) a

Just use order by:
SELECT a.*,
ROW_NUMBER() OVER (PARTITION BY e_type ORDER BY req_no, seq) AS sort_type
FROM tb_listtype a
ORDER BY req_no, sort_type;

Related

Biguqery Row Number Perioding based on specific values

So i have a raw data like this.
| User_id | Month | Device
| 001 | 01 | A
| 001 | 02 | A
| 001 | 03 | B (Base)
| 001 | 04 | A
| 002 | 01 | C
| 002 | 02 | C
| 002 | 03 | B (Base)
| 002 | 04 | B (Base)
| 003 | 01 | A
| 003 | 02 | B (Base)
| 003 | 03 | A
| 003 | 04 | B (Base)
I want to create period that split by B (Base) Device. I thinking about using Row Number but breaks only if meet B or several B's.
The result i want will be like this
| User_id | Month | Device | rn
| 001 | 01 | A | 1
| 001 | 02 | A | 1
| 001 | 03 | B (Base)| 2
| 001 | 04 | A | 3
| 002 | 01 | C | 1
| 002 | 02 | C | 1
| 002 | 03 | B (Base)| 2
| 002 | 04 | B (Base)| 2
| 003 | 01 | A | 1
| 003 | 02 | B (Base)| 2
| 003 | 03 | A | 3
| 003 | 04 | B (Base)| 4
Is there any way we can populate rn like that?
You might consider below query.
SELECT * EXCEPT(flag), COUNTIF(flag) OVER w + 1 AS rn FROM (
SELECT *,
(LAG(Device) OVER w <> 'B' AND Device = 'B') OR
(LAG(Device) OVER w = 'B' AND Device <> 'B') AS flag
FROM sample_table
WINDOW w AS (PARTITION BY User_id ORDER BY Month)
) WINDOW w AS (PARTITION BY User_id ORDER BY Month)
ORDER BY User_id, Month;
+---------+-------+--------+----+
| User_id | Month | Device | rn |
+---------+-------+--------+----+
| 001 | 01 | A | 1 |
| 001 | 02 | A | 1 |
| 001 | 03 | B | 2 |
| 001 | 04 | A | 3 |
| 002 | 01 | C | 1 |
| 002 | 02 | C | 1 |
| 002 | 03 | B | 2 |
| 002 | 04 | B | 2 |
| 003 | 01 | A | 1 |
| 003 | 02 | B | 2 |
| 003 | 03 | A | 3 |
| 003 | 04 | B | 4 |
+---------+-------+--------+----+

ROW_NUMBER() OVER (PARTITION BY)

I am using the ROW_NUMBER() OVER (PARTITION BY....) AS RK command and this is my output:
+--------+-------+------+------------+----+
| SCHOOL | MONTH | YEAR | DATE | RK |
+--------+-------+------+------------+----+
| STAN | 05 | 19 | 2019-05-01 | 1 |
+--------+-------+------+------------+----+
| UCSC | 05 | 19 | 2019-05-01 | 2 |
+--------+-------+------+------------+----+
| BERK | 05 | 18 | 2018-05-01 | 3 |
+--------+-------+------+------------+----+
I do a SELECT * FROM (result from the query above) WHERE RK = 1 and it should return:
STAN 05 19 2019-05-01 1
however, it returns:
UCSC 05 19 2019-05-01 2
I'm not sure why though as the SQL Command logic is correct.

How many different Product has one Market SQL

I try to get an output where there are the Market_id and the number of different Product_id of the market
Table1
| Market_id | Product_id |
| 01 | 105 |
| 01 | 12 |
| 01 | 105 |
| 02 | 34 |
| 02 | 34 |
| 03 | 22 |
| 03 | 22 |
| 03 | 22 |
| 03 | 18 |
output like this
|01 | 2 |
|02 | 1 |
|03 |2 |
and for example if i have a market_id has not Product_id how can i return
| 05 | 0 |
Thanks
Here is the Solution:
select market_id,count(distinct product_id) as count from TableName group by market_id

Duplicate groups of records to fill multiple date gaps in Google BigQuery

I've found a similar question (Duplicating records to fill gap between dates in Google BigQuery), however with a different scenario and the answer there does not apply.
I have data structured like so (which is basically price-change history for multiple products and partners):
+------------+---------+---------+-------+
| date | product | partner | value |
+------------+---------+---------+-------+
| 2017-01-01 | a | x | 10 |
| 2017-01-01 | b | x | 15 |
| 2017-01-01 | a | y | 11 |
| 2017-01-01 | b | y | 16 |
| 2017-01-05 | b | x | 13 |
| 2017-01-07 | a | y | 15 |
| 2017-01-07 | a | x | 15 |
+------------+---------+---------+-------+
What I need is a query (specifically written in BigQuery Standard SQL) that, given a date range (in this case, 2017-01-01 to 2017-01-10), outputs the following result:
+--------------+---------+---------+-------+
| date | product | partner | value |
+--------------+---------+---------+-------+
| 2017-01-01 | a | x | 10 |
| 2017-01-02 | a | x | 10 |
| 2017-01-03 | a | x | 10 |
| 2017-01-04 | a | x | 10 |
| 2017-01-05 | a | x | 10 |
| 2017-01-06 | a | x | 10 |
| 2017-01-07 | a | x | 15 |
| 2017-01-08 | a | x | 15 |
| 2017-01-09 | a | x | 15 |
| 2017-01-10 | a | x | 15 |
| 2017-01-01 | a | y | 11 |
| 2017-01-02 | a | y | 11 |
| 2017-01-03 | a | y | 11 |
| 2017-01-04 | a | y | 11 |
| 2017-01-05 | a | y | 11 |
| 2017-01-06 | a | y | 11 |
| 2017-01-07 | a | y | 15 |
| 2017-01-08 | a | y | 15 |
| 2017-01-09 | a | y | 15 |
| 2017-01-10 | a | y | 15 |
| 2017-01-01 | b | x | 15 |
| 2017-01-02 | b | x | 15 |
| 2017-01-03 | b | x | 15 |
| 2017-01-04 | b | x | 15 |
| 2017-01-05 | b | x | 13 |
| 2017-01-06 | b | x | 13 |
| 2017-01-07 | b | x | 13 |
| 2017-01-08 | b | x | 13 |
| 2017-01-09 | b | x | 13 |
| 2017-01-10 | b | x | 13 |
| 2017-01-01 | b | y | 16 |
| 2017-01-02 | b | y | 16 |
| 2017-01-03 | b | y | 16 |
| 2017-01-04 | b | y | 16 |
| 2017-01-05 | b | y | 16 |
| 2017-01-06 | b | y | 16 |
| 2017-01-07 | b | y | 16 |
| 2017-01-08 | b | y | 16 |
| 2017-01-09 | b | y | 16 |
| 2017-01-10 | b | y | 16 |
+--------------+---------+---------+-------+
Basically a price history with all date gaps filled, for every combination of product and partner.
I'm having a hard time figuring out how to get this done, especially how to generate multiple rows for the same date where no price change has happened. Any ideas?
Try below
#standardSQL
WITH history AS (
SELECT '2017-01-01' AS d, 'a' AS product, 'x' AS partner, 10 AS value UNION ALL
SELECT '2017-01-01' AS d, 'b' AS product, 'x' AS partner, 15 AS value UNION ALL
SELECT '2017-01-01' AS d, 'a' AS product, 'y' AS partner, 11 AS value UNION ALL
SELECT '2017-01-01' AS d, 'b' AS product, 'y' AS partner, 16 AS value UNION ALL
SELECT '2017-01-05' AS d, 'b' AS product, 'x' AS partner, 13 AS value UNION ALL
SELECT '2017-01-07' AS d, 'a' AS product, 'y' AS partner, 15 AS value UNION ALL
SELECT '2017-01-07' AS d, 'a' AS product, 'x' AS partner, 15 AS value
),
daterange AS (
SELECT date_in_range
FROM UNNEST(GENERATE_DATE_ARRAY('2017-01-01', '2017-01-10')) AS date_in_range
),
temp AS (
SELECT d, product, partner, value, LEAD(d) OVER(PARTITION BY product, partner ORDER BY d) AS next_d
FROM history
ORDER BY product, partner, d
)
SELECT date_in_range, product, partner, value
FROM daterange
JOIN temp
ON daterange.date_in_range >= PARSE_DATE('%Y-%m-%d', temp.d)
AND (daterange.date_in_range < PARSE_DATE('%Y-%m-%d', temp.next_d) OR temp.next_d IS NULL)
ORDER BY product, partner, date_in_range

Select values of a column into one row - SQL Server

I want to select in one row the value of a column that appears in multiple rows, I have the table Solution:
| StudentID | SolutionDate | SolutionTime | SongID |
----------------------------------------------------
| 0824616 | 2015-09-20 | 00:07:00 | 01 |
| 0824616 | 2015-09-20 | 00:05:00 | 02 |
| 0824616 | 2015-09-21 | 00:07:40 | 01 |
| 0824616 | 2015-09-21 | 00:10:00 | 03 |
| 0824616 | 2015-09-23 | 00:04:30 | 03 |
| 0824616 | 2015-09-23 | 00:11:30 | 03 |
I want to group the records by StudentID and SongID.
The expected output is:
| StudentID | SongID | TimeA | TimeB | TimeC |
-------------------------------------------------------
| 0824616 | 01 | 00:07:00 | 00:07:40 | NULL |
| 0824616 | 02 | 00:05:00 | NULL | NULL |
| 0824616 | 03 | 00:10:00 | 00:04:30 | 00:11:30 |
There are 3 records by StudentID-SongID at the most. I'm using SQL Server 2012.
Try with window function first to number the rows and then use conditional aggregation:
;with cte as(select *, row_number() over(partition by studentid, songid
order by solutiondate, solutiontime) rn from tablename)
select studentid,
songid,
max(case when rn = 1 then solutiontime end) as timea,
max(case when rn = 2 then solutiontime end) as timeb,
max(case when rn = 3 then solutiontime end) as timec
from cte
group by studentid, songid