I have a database table that represents concert hall and it looks as following:
Columns: ActionID, RegionName, RowNumber, Price, Quantity
The sample data:
ActionID RegionName RowNumber Price Quantity
1 Region1 22 8000 7
1 Region1 - 8000 1
1 Region2 10 5000 2
1 Region2 10 5000 2
1 Region2 10 5000 1
I should display particular regions with overall quantity per region grouped by ActionID, RegionName, Price and Quantity.
1 Region1 22 8000 8
1 Region2 10 5000 5
As you can see the RowNumber should be displayed, but not taken into account in grouping.
How can I do that?
You could use a CTE and ranking function like ROW_NUMBER:
WITH CTE AS
(
SELECT t.*,
rn = ROW_NUMBER()OVER(Partition By ActionID, RegionName, Price
Order By RowNumber),
OverallQuantity = SUM(Quantity) OVER (Partition By ActionID, RegionName, Price)
FROM dbo.TableName t
)
SELECT ActionID, RegionName, RowNumber, Price, Quantity = OverallQuantity
FROM CTE
WHERE RN = 1
Result:
ActionID RegionName RowNumber Price Quantity
1 Region1 - 8000 8
1 Region2 10 5000 5
Demo
You could use something like this:
SELECT ActionId,
RegionName,
MAX(RowNumber),
MAX(Price),
SUM(Quantity)
FROM #tblTest
GROUP BY ActionId, RegionName
But if there are more RowNumber or Price, it should be modified the query
You can apply a MAX or MIN to collapse the rows:
SELECT MAX(ActionID), RegionName, MAX(RowNumber), MAX(Price), SUM(Quantity)
FROM my_table
GROUP BY RegionName
This obviously gets more complicated if you have multiple ActionID or RowNumber or Price per region. In that case, only use this if you don't care which one of these multiple values you get back.
Related
I am trying to create a query for getting the current streak in MySQL based on status
ID
Dated
Status
1
2022-03-08
1
2
2022-03-09
1
3
2022-03-10
0
4
2022-03-11
1
5
2022-03-12
0
6
2022-03-13
1
7
2022-03-14
1
8
2022-03-16
1
9
2022-03-18
0
10
2022-03-19
1
11
2022-03-20
1
In the above table current streak should be 2( i.e 2022-03-20 - 2022-03-19) based on status 1. Any help or ideas would be greatly appreciated!
WITH cte AS (
SELECT SUM(Status) OVER (ORDER BY Dated DESC) s1,
SUM(NOT Status) OVER (ORDER BY Dated DESC) s2
FROM table
)
SELECT MAX(s1)
FROM cte
WHERE NOT s2;
SELECT DATEDIFF(MAX(CASE WHEN Status THEN Dated END),
MAX(CASE WHEN NOT Status THEN Dated END))
FROM table
and so on...
This is a gaps and islands problem. In your case, you want the island of status 1 records which occurs last. We can use the difference in row numbers method, assuming you are using MySQL 8+.
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY Dated) rn1,
ROW_NUMBER() OVER (PARTITION BY Status ORDER BY Dated) rn2
FROM yourTable
),
cte2 AS (
SELECT *, RANK() OVER (ORDER BY rn1 - rn2 DESC) rnk
FROM cte
WHERE Status = 1
)
SELECT ID, Dated, Status
FROM cte2
WHERE rnk = 1
ORDER BY Dated;
Demo
We can use 2 one row CTE's to find the latest date where the status was not the same as the latest one and then count the records superieur.
**Schema (MySQL v8.0)**
create table t(
ID int,
Dated date,
Status int);
insert into t values
(1,'2022-03-08',1),
(2,'2022-03-09',1),
(3,'2022-03-10',0),
(4,'2022-03-11',1),
(5,'2022-03-12',0),
(6,'2022-03-13',1),
(7,'2022-03-14',1),
(8,'2022-03-16',1),
(9,'2022-03-18',0),
(10,'2022-03-19',1),
(11,'2022-03-20',1);
---
**Query #1**
with latest AS
(SELECT
dated lastDate,
status lastStatus
from t
order by dated desc
limit 1 ),
lastDiff as
(select MAX(dated) diffDate
from t,latest
where not status = lastStatus
)
select count(*)
from t ,lastDiff
where dated > diffDate;
| count(*) |
| -------- |
| 2 |
---
[View on DB Fiddle](https://www.db-fiddle.com/)
We could also consider using datediff() to find the number of days that the streak has lasted which might be more interesting than count() seeing as there are some days where there is no record.
Trying to get the 2nd transaction month details for all the customers
Date User_id amount
2021-11-01 1 100
2021-11-21 1 200
2021-12-20 2 110
2022-01-20 2 200
2022-02-04 1 50
2022-02-21 1 100
2022-03-22 2 200
For every customer get all the records in the month of their 2nd transaction (There can be multiple transaction in a month and a day by a particular user)
Expected Output
Date User_id amount
2022-02-04 1 50
2022-02-21 1 100
2022-01-20 2 200
You can use dense_rank:
select Date, User_id, amount from
(select *, dense_rank() over(partition by User_id order by year(Date), month(date)) r
from table_name) t
where r = 2;
Fiddle
If dense_rank is an option you can:
with cte1 as (
select *, extract(year_month from date) as yyyymm
from t
), cte2 as (
select *, dense_rank() over (partition by user_id order by yyyymm) as dr
from cte1
)
select *
from cte2
where dr = 2
Note that it is possible to write the above using one cte.
I have a table with id, city_id, and stock which looks like this.
id
city_id
stock
1
1
1000
2
2
500
3
3
11000
4
2
600
5
3
12000
6
1
2000
9
3
13000
10
1
3000
11
1
4000
12
2
700
To select the latest stock values for each city_id I used the following query, which works fine.
SELECT `stock`
FROM `stock_table`
WHERE id in ( SELECT MAX(id)
FROM `stock_table`
GROUP BY city_id
);
It returns
stock
13000
4000
700
Now I want to select 2nd latest stock entry for each city_id. So the output should be like the following table.
stock
12000
3000
600
Any help is greatly appreciated. Thanks!
In MySQL 8 you can use the row_number() window function to assign a number to each row ordered by the id per partition of city_id. Then just filter on that being 2 (in your example; you can use any number).
SELECT x.stock
FROM (SELECT s.stock,
row_number() OVER (PARTITION BY s.city_id
ORDER BY s.id DESC) rn
FROM stock_table s) x
WHERE x.rn = 2;
u can use group by with row number and get rownumber 2
ROW_NUMBER() OVER (PARTITION BY city_id ORDER By id) as ROW
I have trouble adding and accumulating my amounts per id,
I use this solution but it doesn't work and it adds up all the ids,
id product_id quantity acumulado
168 190 1 1
169 190 3 4
170 195 1 5
171 190 25.60 30.60
172 190 1 31.60
I use this:
SET #csum := 0;
UPDATE sma_sale_items
SET acumulado = (#csum := #csum + quantity)
ORDER BY id, product_id;
any solution? ineed this
id product_id quantity acumulado
168 190 1 1
169 190 3 4
170 195 1 1
171 190 25.60 29.60
172 190 1 30.60
For version 5.7 ?
You can use a SELECT statement containing window analytic function instead of an UPDATE statement :
SELECT id, product_id, quantity, SUM(quantity) OVER (ORDER BY id) AS acumulado
FROM sma_sale_items
acumulado column shouldn't need to be stored within a table being a computable column.
Demo1
If you still prefer UPDATE, then use :
UPDATE sma_sale_items s1
JOIN (
SELECT id, product_id, SUM(quantity) OVER (ORDER BY id) AS acumulado
FROM sma_sale_items
ORDER BY id
) s2 ON s1.ID=s2.ID
SET s1.acumulado = s2.acumulado;
Demo2
UPDATE : Depending on the last edit consider using
SUM(quantity) OVER (PARTITION BY product_id ORDER BY id) AS acumulado
instead of SUM(quantity) OVER (ORDER BY id) AS acumulado
by adding PARTITION BY product_id in order to distinguish the sums grouped by product_id
Demo3
Suppose:
Table Name : purchase
id pur_Date pur_value
1 01/02/16 5000.00
2 02/02/16 2500.00
3 05/02/16 7000.00
Table Name : Sale
id sale_Date sale_value
1 02/02/16 5050.00
2 02/02/16 2555.00
3 05/02/16 9000.00
4 05/02/16 7000.00
5 05/02/16 7250.00
Run a query...............
Result would like below:
Date Value
01/02/16 5000.00
02/02/16 2500.00
02/02/16 5050.00
02/02/16 2555.00
05/02/16 7000.00
05/02/16 9000.00
05/02/16 7000.00
05/02/16 7250.00
Please solve it.
Use UNION ALL.
select t.* from
(
select pur_Date as Date, pur_value as Value
from purchase
union all
select sale_Date as Date, sale_value as Value
from sale
)t
order by t.Date;
try this.
(SELECT pur_Date, pur_value FROM purchase)
UNION ALL
(SELECT Date, Value FROM Sale)
ORDER BY 1;
Use Union All query and sort by another assumed string Date by key as:
SQL>
select pur_Date as Date, pur_value as Value
from purchase
union all
select sale_Date as Date, sale_value as Value
from sale
order by 1;