Inner Selection, Sum of colunms with conditions order by Region - mysql

After selection I get my new clear table like
SELECT a.sta_name, a.product, a.product_id, a.date, a.active, a.region_id, a.brand, a.brand_id from
(SELECT DISTINCT sta_name, product, product_id, date, active, region_id, brand, brand_id FROM `sv_ziyaret`
WHERE brand_id=2 and date between "2021-07-00" and "2021-07-31" order by region_id) a
so I get my values DISTINCT
sta_name | product | product_id | active | region_id | brand | brand_id| date |
3M A 1 1 1 A1 1 2021-07-02
2M A 1 0 1 A1 1 2021-07-02
5M B 2 0 1 A1 1 2021-07-05
4M B 2 0 2 A1 1 2021-07-06
M A 2 1 2 A1 1 2021-07-10
2M C 3 1 4 A1 1 2021-07-12
3M B 2 1 4 A1 1 2021-07-15
sta_name never repeats with same region_id, products do. What I try to get is
product_id | product | active_on | active_off | region_id
1 A 12 2 1
1 A 7 9 2
2 B 6 10 1
2 B 16 5 2
3 C 10 5 4
My main purpose is to be able to calculate percentage of product's existance in each region. In instance A product has %80 on sale on shalves at region A.
Manualy I am able to get each products result as
SELECT
product, product_id, region_id,
SUM(CASE WHEN sv_ziyaret.active = 1 THEN 1 ELSE 0 END) var,
SUM(CASE WHEN sv_ziyaret.active = 0 THEN 1 ELSE 0 END) yok
FROM
`sv_ziyaret`
WHERE
product_id=37 and date between "2021-07-00" and "2021-07-31" and region_id=7 order by region_id
but this is not a good solution I need it to be able to get each product by giving its brand_id only.
Hope to get a hand realy would same my weak

You are very close to the general solution. You just need GROUP BY AND LAST_DAY().
SELECT
product, product_id, region_id, LAST_DAY(date) month_ending,
SUM(CASE WHEN sv_ziyaret.active = 1 THEN 1 ELSE 0 END) var,
SUM(CASE WHEN sv_ziyaret.active = 0 THEN 1 ELSE 0 END) yok
FROM
sv_ziyaret
WHERE
GROUP BY product, product_id, region_id, LAST_DAY(date)
ORDER BY region_id, LAST_DAY(date), product_id;

Related

Merging Multiple Queries - Same Table

I have 1 table called itemmovement : It has Item Id , Quantity In , Quantity Out , Invoice Id, Date. I need to make in one query to show how many pieces are sold and beside the sold column there will be the current on hand quantity .
itemmovement
Id itemid qtyin qtyout invid purchasereturnid date
1 1 10 2019-01-04
2 2 8 2019-01-06
3 2 2 1 2019-01-08
4 1 3 2 2019-01-12
5 2 1 2019-02-04
6 3 4 2019-03-04
7 1 1 3 2019-04-04
8 1 1 1 2019-04-14
9 3 1 2 2019-04-24
I need the query to show this result
Id itemid Sold Quantity OnHandQty
1 1 4 5
2 2 2 7
3 3 0 3
I'm Trying to use this query but not working
SELECT *
FROM
(SELECT itmv.itemid,
sum(itmv.qtyout)-sum(itmv.qtyin)
FROM itemmovement itmv
WHERE (itmv.systemdate BETWEEN '2019-01-01' AND '2019-06-01')
AND invid>0
GROUP BY itmv.itemid) AS result1,
(SELECT sum(itmv2.qtyin)-sum(itmv2.qtyout)
FROM itemmovement itmv2
WHERE itmv.itemid=itmv2.itemid
GROUP BY itmv2.itemid) AS result2
ORDER BY sum(itmv.qtyin)-sum(itmv.qtyout)
I'm getting :
Unknown column 'itmv.itemid' in 'where clause it for this syntax :
where itmv.itemid = itmv2.itemid
Here's your query.
select itemid
, sum(case when COALESCE(invid,0) > 0 then qtyout else 0 end) as Sold_Qantity
, sum(qtyin)-sum(qtyout) as OnHandQty
from itemmovement
group by itemid

How to LEFT JOIN more than 2 tables to get no records?

I want to get the date of this week and the total sum of total_price even there is no transaction on the specific date. The problem is when I change the value of tbl_barangay.city_id into 2, all the data of tbl_barangay.city_id = 1 is included. I want to get all records according to the value of tbl_barangay.city_id. How can I left join more than 2 tables so I can get the expected data?
Sample data
tbl_calendar tbl_city tbl_tran
date_id date city_id city_name tran_id tran_date city_id
1 2019-08-19 1 Sala 1 2019-08-19 1
2 2019-08-20 2 Marinig 2 2019-08-20 1
3 2019-08-21 3 Pulo 3 2019-08-23 2
4 2019-08-22
5 2019-08-23
6 2019-08-24
7 2019-08-25
tbl_tran_details
detail_id item total_price tran_id
1 Item1 20 1
2 Item2 20 1
2 Item3 30 2
2 Item1 30 3
Expected data if the tbl_city.city_id = 1
Date Total
2019-08-19 40
2019-08-20 30
2019-08-21 0
2019-08-22 0
2019-08-23 0
2019-08-24 0
and if the tbl_city.city_id = 2
Date Total
2019-08-19 0
2019-08-20 0
2019-08-21 0
2019-08-22 0
2019-08-23 30
2019-08-24 0
SELECT tbl_calendar.date Date,
SUM(IFNULL(tbl_tran_details.total_price,0)) Total FROM tbl_calendar
LEFT JOIN
tbl_tran ON tbl_calendar.date = tbl_tran.tran_date
LEFT JOIN
tbl_tran_details ON tbl_tran.tran_id = tbl_tran_details.tran_id
LEFT JOIN
tbl_city ON tbl_tran.city_id = tbl_city.city_id AND tbl_city.city_id = 2
WHERE
YEAR(tbl_calendar.date) = YEAR(NOW())
AND
WEEK(tbl_calendar.date) = WEEK(NOW())
GROUP BY
tbl_calendar.date
The problem is that you filter the cities in the wrong table because you want to get the sum of transactions for a certain city from the tbl_tran table, but you filter the cities in the tbl_city - which you do not even use in this query.
...
FROM (tbl_calendar
LEFT JOIN
tbl_tran ON tbl_calendar.date = tbl_tran.tran_date AND tbl_tran.city_id = 2)
LEFT JOIN
tbl_tran_details ON tbl_tran.tran_id = tbl_tran_details.tran_id
...

multiple records per row query

I have a table (in mysql) like this:
TABLE1
Id Name Age
---------------
1 John 22
2 Mary 17
3 Peter 21
4 Agnes 34
5 Steve 14
6 Bart 26
7 Bob 32
8 Vince 18
...
What I am looking for is a SELECT statement, where I can get 4 records in a row. I mean, the result of the select statement would be:
Id1 Name1 Age1 Id2 Name2 Age2 Id3 Name3 Age3 Id4 Name4 Age4
-----------------------------------------------------------
1 John 22 2 Mary 17 3 Peter 21 4 Agnes 34
5 Steve 14 6 Bart 26 7 Bob 32 8 Vince 18
...
I guess it would be like a pivot...
Is this possible? If it is, then how can I achieve it?
I need to populate a report by showing 4 records on a row, so I would like to be able to do it from a datasource that returns this exact structure. So on first band/row there will be
rec1,rec2,rec3,rec4
then on second row:
rec5,rec6,rec7,rec8
and so on.
My first idea was to merge 4 queries that return every 5th record starting with 1,2,3,4 but I'm not exactly sure...
Can you help?
You can do this with arithmetic on the id and group by:
select (case when id % 4 = 1 then id end) as id1,
(case when id % 4 = 1 then name end) as name1,
(case when id % 4 = 1 then age end) as age1,
(case when id % 4 = 2 then id end) as id2,
(case when id % 4 = 2 then name end) as name2,
(case when id % 4 = 2 then age end) as age2,
(case when id % 4 = 3 then id end) as id3,
(case when id % 4 = 3 then name end) as name3,
(case when id % 4 = 3 then age end) as age3,
(case when id % 4 = 0 then id end) as id4,
(case when id % 4 = 0 then name end) as name4,
(case when id % 4 = 0 then age end) as age4
from t
group by floor((id - 1) / 4);
If the id doesn't increment without gaps, then you can generate one using:
from (select t.*, (#rn := #rn + 1) as seqnum
from t cross join
(select #rn := 0) params
order by id
) t

SQL consolidate data and turn them into columns

So here's what my data table looks like:
TeamNum Round Points1 Points2
1 1 5 21
2 1 10 20
3 1 9 29
1 2 6 22
2 2 11 21
3 2 10 30
1 3 80 50
I also have a second table with this:
TeamNum TeamName
1 goteam1
2 goteam2
3 goteam4-1
I want SQL to take it and turn it into this:
Team Round1 Round2 Round3 TeamName
1 (points1+points2 of round1) (same but for r2) (same but for r3) goteam1
2 (points1+points2 of round1) (same but for r2) (same but for r3) goteam2
3 (points1+points2 of round1) (same but for r2) (same but for r3) goteam4-1
And a sample output from the tables above would be:
Team Round1 Round2 Round3 TeamName
1 26 28 130 goteam1
2 30 32 0 goteam2
3 38 40 0 goteam4-1
The actual data has a bunch of "points1" and "points2" columns, but there are only 3 rounds.
I am very new to SQL and this is all I have right now:
select
`data`.`round`,
`data`.`teamNumber`,
sum(`Points1`) + sum(`Points2`) as score
from `data` join `teams` ON `teams`.`teamNumber` = `data`.`teamNumber`
group by `data`.`teamNumber` , `round`
order by `data`.`teamNumber`, `data`.`round`
But it doesn't return anything at all. If I remove the join statement, it shows everything like I want, but doesn't consolidate Round1, 2, and 3 as columns, they are each separate rows. Can you guys help me out? Thanks!
Use conditional aggregation
SELECT t.teamnumber, t.teamname,
SUM(CASE WHEN d.round = 1 THEN d.points1 + d.points2 ELSE 0 END) round1,
SUM(CASE WHEN d.round = 2 THEN d.points1 + d.points2 ELSE 0 END) round2,
SUM(CASE WHEN d.round = 3 THEN d.points1 + d.points2 ELSE 0 END) round3
FROM data d JOIN teams t
ON d.teamnumber = t.teamnumber
GROUP BY t.teamnumber, t.teamname
Output:
| TEAMNUMBER | TEAMNAME | ROUND1 | ROUND2 | ROUND3 |
|------------|-----------|--------|--------|--------|
| 1 | goteam1 | 26 | 28 | 130 |
| 2 | goteam2 | 30 | 32 | 0 |
| 3 | goteam4-1 | 38 | 40 | 0 |
Here is SQLFiddle demo
No need to aggregate:
SELECT
t.teamnumber,
COALESCE(r1.points1 + r1.points2, 0) AS round1,
COALESCE(r2.points1 + r2.points2, 0) AS round2,
COALESCE(r3.points1 + r3.points2, 0) AS round3,
t.teamname
FROM teams t
LEFT JOIN data r1 ON r1.teamnumber = t.teamnumber AND r1.round = 1
LEFT JOIN data r2 ON r2.teamnumber = t.teamnumber AND r2.round = 2
LEFT JOIN data r3 ON r3.teamnumber = t.teamnumber AND r3.round = 3
Something like this:
select teams.teamNumber,
SUM(CASE WHEN Round=1 THEN `Points1`+`Points2` ELSE 0 END)as Round1,
SUM(CASE WHEN Round=2 THEN `Points1`+`Points2` ELSE 0 END)as Round2,
SUM(CASE WHEN Round=3 THEN `Points1`+`Points2` ELSE 0 END)as Round3,
teams.teamName
from `data` join `teams` ON `teams`.`teamNumber` = `data`.`teamNumber`
group by teamnumber , teamname
order by `data`.`teamNumber`, `data`.`round`

mysql query find between past dates and current dates

I have two tables one is simple like this named orders and due_dates
id | name | price | due_id | status
1 a 10 1 0
2 b 20 1 0
3 c 30 1 1
4 d 40 2 0
4 d 40 2 1
and an other table with dates
id | start_date | end_date
1 2011-04-01 2011-05-21
2 2011-07-01 2011-07-15
what I am trying to find is all orders from past period with status 0 and from the current period all records with status 0 and 1 i know how to get orders from current period
SELECT *
FROM orders
INNER JOIN due_dates ON orders.due_id = due_dates.due_id
AND now() BETWEEN due_dates.start_date AND due_dates.end_date
AND status in (0,1);
SELECT *
FROM orders
INNER JOIN due_dates ON orders.due_id = due_dates.due_id
WHERE
(status in (0,1) and now() BETWEEN due_dates.start_date AND due_dates.end_date) OR
(status = 0 AND due_dates.end_date < now())