I have this SELECT:
SELECT
m.`maschine-name` AS byMaschine,
q.`mname` AS byMName,
SUM(YEAR(q.`created`) = YEAR(CURDATE())) AS total
FROM qualitaet q INNER JOIN
maschinen m
ON m.maschine = q.maschine
WHERE
q.`status`='1'
GROUP BY
q.maschine, q.mname;
to get all results for the current year and it looks like this:
| maschine-name | mname | total |
| TYP 1 | 0 | 4 |
| TYP 2 | 3 | 4 |
| TYP 2 | 4 | 4 |
| TYP 3 | 0 | 4 |
| TYP 4 | 0 | 4 |
see SQL Fiddle here
But i want to SELECT it as fiscal year (financial year) starting at >= Oct, 1 to get this result:
| maschine-name | mname | total |
| TYP 1 | 0 | 3 |
| TYP 2 | 3 | 2 |
| TYP 2 | 4 | 0 |
| TYP 3 | 0 | 2 |
| TYP 4 | 0 | 2 |
i have different Date statements which work all, but the fiscal year drives me crazy :-(
show data for TODAY:
SUM(DATE(created) = CURDATE()) AS total
show data for CURRENT WEEK:
SUM(YEARWEEK(q.`created`, 1) = YEARWEEK(CURRENT_DATE, 1)) AS total
show data for CURRENT MONTH:
SUM(q.`created` >= CURDATE() - INTERVAL DAY(CURDATE())-1 DAY) AS total
show data for CURRENT YEAR:
SUM(YEAR(q.`created`) = YEAR(CURDATE())) AS total
Is there a way to get this result from above?
Best regards and a happy new year ;-)
I did it with MAKEDATE. Startdate is Oct, 1
SUM(q.`created` >= MAKEDATE(year(now()-interval 1 year),1) + interval 9 month) AS total
see SQLFiddle here
complete SELECT:
SELECT
m.`maschine-name` AS byMaschine,
q.`mname` AS byMName,
SUM(q.`created` >= MAKEDATE(year(now()-interval 1 year),1) + interval 9 month) AS total
FROM qualitaet q INNER JOIN
maschinen m
ON m.maschine = q.maschine
WHERE
q.`status`='1'
GROUP BY
q.maschine, q.mname;
Now i receive this result:
| maschine-name | mname | total |
| TYP 1 | 0 | 3 |
| TYP 2 | 3 | 2 |
| TYP 2 | 4 | 0 |
| TYP 3 | 0 | 2 |
| TYP 4 | 0 | 2 |
Related
I need a help to create a view in MySQL.
I have a table in the name of competitions like below:
+---------+-----+-----+-----+
|id| name |rank1|rank2|rank3|
+--+------+-----+-----+-----+
| 1| cmpt1| 4 | 3 | 9 |
| 2| cmpt2| 3 | 7 | 8 |
| 3| cmpt3| 4 | 1 | 2 |
| 4| cmpt4| 5 | 8 | 4 |
| 5| cmpt5| 9 | 3 | 2 |
| 6| cmpt6| 1 | 8 | 2 |
+--+------+-----+-----+-----+
the rank1,2,3 values refer to the player id who has such rank at the end of that competition.
Now I want to create a MySQL view to show each player's total medals. Rank 1, 2, and 3 received gold, silver, and bronze medal respectively.
The output of the view will be like following table:
+------+------------+-------------+-------------+
|player| gold_medals|silver_medals|bronze_medals|
+------+------------+-------------+-------------+
| 1 | 4 | 7 | 1 |
| 2 | 7 | 0 | 9 |
| 3 | 1 | 4 | 6 |
| 4 | 0 | 2 | 8 |
| 5 | 2 | 8 | 0 |
| 6 | 3 | 1 | 1 |
+------+------------+-------------+-------------+
Thanks in advance
I assumed you have another table for list players :
select p.playerid
, count(case when playerid = rank1 then 1 end) gold_medals
, count(case when playerid = rank2 then 1 end) silver_medals
, count(case when playerid = rank3 then 1 end) bronze_medals
from
players p
left join ranks r
on p.playerid in (rank1, rank2, rank3)
group by p.playerid
playerid | gold_medals | silver_medals | bronze_medals
-------: | ----------: | ------------: | ------------:
1 | 1 | 1 | 0
2 | 0 | 0 | 3
3 | 1 | 2 | 0
4 | 2 | 0 | 1
5 | 1 | 0 | 0
6 | 0 | 0 | 0
7 | 0 | 1 | 0
8 | 0 | 2 | 1
9 | 1 | 0 | 1
db<>fiddle here
You can unpivot and aggregate:
select playerid,
sum(ranking = 1) as num_gold,
sum(ranking = 2) as num_silver,
sum(ranking = 3) as num_bronze
from ((select rank1 as playerid, 1 as ranking
from ranks
) union all
(select rank2, 2 as ranking
from ranks
) union all
(select rank3, 3 as ranking
from ranks
)
) p
group by playerid;
Note: This only includes players who have a ranking. Your question doesn't include a source of all players, so that seems sufficient.
Here is a db<>fiddle.
Note that older versions of MySQL (pre-5.7 I think) don't support subqueries in the FROM clause of views. Happily that restriction is no longer in force.
I currently have the following simplified tables in my database. The points table contains rows of points awarded to each user for every bid form they have voted in.
I would like to add a column to this table that for each row, it shows the AVERAGE of the previous TWO points awarded to THAT user.
Users
+----+----------------------+
| id | name |
+----+----------------------+
| 1 | Flossie Schamberger |
| 2 | Lawson Graham |
| 3 | Hadley Reilly |
+----+----------------------+
Bid Forms
+----+-----------------+
| id | name |
+----+-----------------+
| 1 | Summer 2017 |
| 2 | Winter 2017 |
| 3 | Summer 2018 |
| 4 | Winter 2019 |
| 5 | Summer 2019 |
+----+-----------------+
Points
+-----+---------+--------------------+------------+------------+
| id | user_id | leave_bid_forms_id | bid_points | date |
+-----+---------+--------------------+------------+------------+
| 1 | 1 | 1 | 6 | 2016-06-19 |
| 2 | 2 | 1 | 8 | 2016-06-19 |
| 3 | 3 | 1 | 10 | 2016-06-19 |
| 4 | 1 | 2 | 4 | 2016-12-18 |
| 5 | 2 | 2 | 8 | 2016-12-18 |
| 6 | 3 | 2 | 4 | 2016-12-18 |
| 7 | 1 | 3 | 10 | 2017-06-18 |
| 8 | 2 | 3 | 12 | 2017-06-18 |
| 9 | 3 | 3 | 4 | 2017-06-18 |
| 10 | 1 | 4 | 4 | 2017-12-17 |
| 11 | 2 | 4 | 4 | 2017-12-17 |
| 12 | 3 | 4 | 2 | 2017-12-17 |
| 13 | 1 | 5 | 16 | 2018-06-17 |
| 14 | 2 | 5 | 12 | 2018-06-17 |
| 15 | 3 | 5 | 10 | 2018-06-17 |
+-----+---------+--------------------+------------+------------+
For each row in the points table I would like an average_points column to be calculated like follows.
The average point column is the average of that users PREVIOUS 2 points. So for the first entry in the table for each user, the average is obviously 0 because there were no previous points awarded to them.
The previous 2 points for each user should be determined using the date column.
The table below is what I would like to have as the final output.
For clarity, to the side of the table, I have added the calculation and numbers used to arrive at the value in the averaged_points column.
+-----+---------+--------------------+------------+-----------------+
| id | user_id | leave_bid_forms_id | date | averaged_points |
+-----+---------+--------------------+------------+-----------------+
| 1 | 1 | 1 | 2016-06-19 | 0 | ( 0 + 0 ) / 2
| 2 | 2 | 1 | 2016-06-19 | 0 | ( 0 + 0 ) / 2
| 3 | 3 | 1 | 2016-06-19 | 0 | ( 0 + 0 ) / 2
| 4 | 1 | 2 | 2016-12-18 | 3 | ( 6 + 0 ) / 2
| 5 | 2 | 2 | 2016-12-18 | 4 | ( 8 + 0 ) / 2
| 6 | 3 | 2 | 2016-12-18 | 5 | ( 10 + 0) / 2
| 7 | 1 | 3 | 2017-06-18 | 5 | ( 4 + 6 ) / 2
| 8 | 2 | 3 | 2017-06-18 | 8 | ( 8 + 8 ) / 2
| 9 | 3 | 3 | 2017-06-18 | 7 | ( 4 + 10) / 2
| 10 | 1 | 4 | 2017-12-17 | 7 | ( 10 + 4) / 2
| 11 | 2 | 4 | 2017-12-17 | 10 | ( 12 + 8) / 2
| 12 | 3 | 4 | 2017-12-17 | 4 | ( 4 + 4 ) / 2
| 13 | 1 | 5 | 2018-06-17 | 7 | ( 4 + 10) / 2
| 14 | 2 | 5 | 2018-06-17 | 8 | ( 4 + 12) / 2
| 15 | 3 | 5 | 2018-06-17 | 3 | ( 2 + 4 ) / 2
+-----+---------+--------------------+------------+-----------------+
I've been trying to use subqueries to solve this issue as AVG doesn't seem to be affected by any LIMIT clause I have.
So far I have come up with
select id, user_id, leave_bid_forms_id, `date`,
(
SELECT
AVG(bid_points)
FROM (
Select `bid_points`
FROM points as p2
ORDER BY p2.date DESC
Limit 2
) as thing
) AS average_points
from points as p1
This is in this sqlfiddle but to be honest I'm out of my depth here.
Am I on the right path? Wondering if someone would be able to show me where I need to tweak things please!
Thanks.
EDIT
Using the the answer below as a basis I was able to tweak the sql to work with the tables provided in the original sqlfiddle.
I have added that to this sqlfiddle to show it working
The corrected sql to match the code above is
select p.*,
IFNULL(( (coalesce(points_1, 0) + coalesce(points_2, 0)) /
( (points_1 is not null) + (points_2 is not null) )
),0) as prev_2_avg
from (select p.*,
(select p2.bid_points
from points p2
where p2.user_id = p.user_id and
p2.date < p.date
order by p2.date desc
limit 1
) as points_1,
(select p2.bid_points
from points p2
where p2.user_id = p.user_id and
p2.date < p.date
order by p2.date desc
limit 1, 1
) as points_2
from points as p
) p;
Although I am about to ask another question about the best way to make this dynamic with the number of previous poingt that need to be averaged.
You can use window functions, which were introduced in MySQL 8.
select p.*,
avg(points) over (partition by user_id
order by date
rows between 2 preceding and 1 preceding
) as prev_2_avg
from p;
In earlier versions, this is a real pain, because MySQL does not support nested correlation clauses. One method is with a separate column for each one:
select p.*,
( (coalesce(points_1, 0) + coalesce(points_2, 0)) /
( (points_1 is not null) + (points_2 is not null) )
) as prev_2_avg
from (select p.*,
(select p2.points
from points p2
where p2.user_id = p.user_id and
p2.date < p.date
order by p2.date desc
limit 1
) as points_1,
(select p2.points
from points p2
where p2.user_id = p.user_id and
p2.date < p.date
order by p2.date desc
limit 1, 1
) as points_2
from p
) p;
I need single SQL query for SELECT list of jobs including SUM() of sme specific detail type.
I have database with transport data. Tables looks like that:
job:
idjob | customer
1 | 45
2 | 38
3 | 15
job-detail:
iddet | idjob | type | value
1 | 1 | range | 100
2 | 1 | range | 85
3 | 1 | range | 12
4 | 1 | price | 64
4 | 1 | price | 5
5 | 1 | note | Some text here
6 | 2 | range | 150
7 | 2 | price | 32
8 | 2 | note | Some text here
9 | 2 | range | 35
I need this output:
idjob | customer | total_range | total_price
1 | 45 | 197 | 69
2 | 38 | 185 | 32
3 | 15 | 0 | 0
you can use left join with conditional aggregation
select a.idjob,customer,
sum(case when type='range' then value end) as total_range,
sum(case when type='price' then value end) as total_price
from job a
left join job-detail b on a.idjob=b.idjob
group by a.idjob,customer
SELECT DISTINCT J.idjob, J.customer,
(SELECT SUM(CONVERT(INT, [VALUE])) FROM [dbo].[job-detail] WHERE TYPE = 'range' AND J.idjob = idjob) AS total_range,
(SELECT SUM(CONVERT(INT, [VALUE])) FROM [dbo].[job-detail] WHERE TYPE = 'price' AND J.idjob = idjob) AS total_price
FROM [dbo].[job] j
LEFT JOIN [dbo].[job-detail] JD ON J.idjob = JD.idjob
We have one table- Product_table:
product_id | company_id | Status | must_show
1 | 23 | 1 | 1
2 | 23 | 1 | 1
3 | 23 | 1 | 0
4 | 23 | 1 | 0
5 | 23 | 0 | 0
6 | 24 | 1 | 0
7 | 24 | 1 | 0
8 | 24 | 1 | 0
9 | 24 | 1 | 0
10 | 24 | 0 | 0
We need to find the max product_id of company where status is 1. For that we are using below query:
select * from Product_table as pt
JOIN (select MAX(product_id) as extid from Product_table) t1 ON t1.extid =
pt.product_id where company_id in (23,24) and status = 1 group by company_id;
Result:
product_id| company_id| Status | must_show
4 | 23 | 1 | 0
9 | 24 | 0 | 0
This query is fine but we have an issue here.
If value for must_show is 1 then we need show max_product id for company with must_show=1 and status=1.
If value for must_show is 0 then we need show max_product id for company with status=1.
Expected Result:
product_id| company_id| Status | must_show
2 | 23 | 1 | 1
9 | 24 | 1 | 0
Please give me the path to find a solution. Thanks!
Please try below query:
select max(t.product_id) product_id, t.company_id, t.status, t.must_show from
( select p1.product_id, p1.company_id, p1.status, p1.must_show
from product_table p1
where status = 1
and must_show = (
select max(must_show) from product_table p2 where p2.company_id = p1.company_id)
) as t group by t.company_id;
Output:
+------------+------------+--------+-----------+
| product_id | company_id | status | must_show |
+------------+------------+--------+-----------+
| 2 | 23 | 1 | 1 |
| 9 | 24 | 1 | 0 |
+------------+------------+--------+-----------+
company_id in (23,24)- I think you don't need this condition as there are only these two company_id present in your table as per your question data.
Am stuck with this for days. wanna group a sql result set by historical dates. so want a result to be grouped by date from each date in the date specified range all the way back in time. Here is my sql so far, but it groups the result by date instead of historical date.
Please help!
SELECT ledger.transdate,
sum(case when transcodes.dtcr = 'C' then ledger.amount else 0 end) Credit,
sum(case when transcodes.dtcr = 'D' then ledger.amount else 0 end) Debit,
sum(case when transcodes.dtcr = 'C' then ledger.amount else 0 end) -
sum(case when transcodes.dtcr = 'D' then ledger.amount else 0 end) Balance
FROM
LEDGER
INNER JOIN TRANSCODES ON (LEDGER.TRANSCODE = TRANSCODES.TRANSCODE)
where ledger.transdate >= '2013-02-28' and ledger.transdate <= '2013-03-01'
group by ledger.transdate
Maybe consider this example...
SELECT * FROM ints;
+---+
| i |
+---+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+---+
SELECT x.i, SUM(y.i) running FROM ints x JOIN ints y ON y.i <= x.i GROUP BY i;
+---+---------+
| i | running |
+---+---------+
| 0 | 0 |
| 1 | 1 |
| 2 | 3 |
| 3 | 6 |
| 4 | 10 |
| 5 | 15 |
| 6 | 21 |
| 7 | 28 |
| 8 | 36 |
| 9 | 45 |
+---+---------+
If I understood you correctly, and you want to group by date-only part of transdate field, you can use Date() function, i.e. ... group by Date(transdate)
Your answer can be found here:
http://www.codeproject.com/Articles/300785/Calculating-simple-running-totals-in-SQL-Server