I have table with name orders:
id id_o value date
1 1 400 2014-09-30
2 1 300 2014-09-30
3 1 200 2014-09-30
4 2 100 2014-09-30
5 2 200 2014-09-30
6 3 50 2014-09-29
7 3 100 2014-09-29
8 4 300 2014-09-29
9 5 600 2014-09-28
I need select every order grouped by id_o with sum(value)< 700 and from this selected table i need display data grouped by datum.
I use multiple select:
select date, sum(mno) as mn
from (
select date,sum(value) as 'mno'
from orders
group by id_o
having sum(value)<700
) table_alias
group by date
This is result:
date mn
2014-09-30 300
2014-09-29 450
2014-09-28 600
Is there any possibility to replace or to simplify this correlated query?
Your inner query is invalid. It groups by id_o, but selects by date. In order to solve this, add an additional column to the inner queries grouping (assuming date is always the same for every id_o). You can enable strong checking by enabling the sql_mode's ONLY_FULL_GROUP_BY. Full example in SQL fiddle.
SELECT
date,
SUM(mno) AS mn
FROM (
SELECT
id_o,
date,
SUM(value) AS mno
FROM orders
GROUP BY
id_o,
date
HAVING
SUM(value) < 700
) totalPerOrder
GROUP BY date
MySQL allows this type of queries, but it's not common to do so. Consider the following data:
id id_o value date
1 1 400 2014-09-29
2 1 300 2014-09-30
3 1 200 2014-09-30
What date(s) would SELECT date, SUM(value) FROM orders GROUP BY id_o return? It could be the first, last, average, most common one, but better make it explicit. Any other DBMS wouldn't let you execute this query.
Other than that, I would rename some of the columns to be more expressive. mn, mn_o and id_o are examples of this. Also value describes nothing, anything can be a value. Even the date field could have been called value. The query itself seems fine (take care if possibly missing indexes though).
Related
I have a list of IDs and the detail of the trips they've taken. I want to see how many trips each ID takes in a day on average but I don't know how to write this query. The data I have in my table is something like this:
ID
Ride_id
Date
1
123
2022-3-4
1
124
2022-3-4
1
111
2021-2-8
2
584
2019-4-18
2
256
2019-4-18
2
805
2020-5-8
2
127
2020-5-8
2
457
2020-5-8
3
100
2021-4-7
3
101
2021-4-7
3
202
2021-5-17
3
741
2021-5-17
So basically, the average rides ID=1 takes is 1.5 and the average rides ID=2 takes is 2.5 and so on. I need a query to calculate and show the result like this:
ID
Average_of_daily_trips
1
1.5
2
2.5
3
2
My current query uses only one condition: WHERE ID in ()
First count the trips on each day for each id, then make the average over those counts.
select id, avg(trips)
from (select id, count(*) as trips
from trips
-- where id in(1,2,3)
group by id, date) t
group by id
If you need to, you can uncomment the where clause in the subquery to filter for particular ids ...
I have a query that I want to add a colum to. It should contain the amount of how many times a value of a specific column appears in that table.
My current attempt
SELECT cleaning.*,
(SELECT COUNT(*)
FROM cleaning
WHERE column_b = cleaning.column_b)
AS multicleanamount
FROM cleaning
is counting every single row as it is just comparing a column with same column - I understand the reason.
So the current (wrong) result is
column_a
column_b
multicleanamount
12
300
7
13
321
7
14
300
7
15
330
7
16
330
7
17
351
7
18
330
7
What I am missing now is how do I tell the sub-Select to compare with the current value of cleaning.column_b from the very first line? (which is in the cleaning.*)
2bh it was pretty easy in my head at first and it also would be if I'd compare to a static value like '300' but that table has 74 K entries. This has to be dynamic.
My desired output is
column_a
column_b
multicleanamount
12
300
2
13
321
1
14
300
2
15
330
3
16
330
3
17
351
1
18
330
3
I hope that is understandable. If not please tell me and I will try to specify even more.
Use table aliases so you can distinguish the cleaning table in the subquery from the table in the main query. In your query, WHERE column_b = cleaning.column_b is comparing the column with itself, so the condition is always true and you're counting all the rows.
SELECT c1.*,
(SELECT COUNT(*)
FROM cleaning AS c2
WHERE c1.column_b = c2.column_b)
AS multicleanamount
FROM cleaning AS c1
It may also be better to write this as a JOIN instead of correlated subquery:
SELECT c1.*, c2.multicleanamount
FROM cleaning AS c1
JOIN (
SELECT column_b, COUNT(*) AS multicleanamount
FROM cleaning
GROUP BY column_b
) AS c2 ON c1.column_b = c2.column_b
I have the following sample data:
Date
amount
type
grouping_value
2021-03-01
10
1
2021-03-04
15
3
2021-03-16
32
4
2021-03-16
1
2
a
2021-03-16
4
3
a
2021-03-16
48
4
a
and my expected result is:
Date
amount
type
grouping_value
2021-03-01
10
1
2021-03-04
15
3
2021-03-16
32
4
2021-03-16
53
9
a
with the following query:
SELECT date, SUM(amount), type, grouping_value
FROM table
GROUP BY date, grouping_value
The query is still untested but should work for all requirements but one.
As you can see from the results, the query should group by date and grouping_value. So the first three rows of my input data will remain as they are, the other three will be grouped in one movement. What I want to do is: when some rows are grouped show 9 as type instead of one of the types that are grouped. If a row is not grouped then show the original type.
The condition to group is that grouping_value is not blank.
How can I tell mysql to replace if it is grouping only?
Use COUNT(*) to tell if the row is in a group.
SELECT date, SUM(amount), IF(COUNT(*) > 1, 9, MAX(type)) AS type, grouping_value
FROM table
GROUP BY date, grouping_value
I have a table with the following data:
id date name schedulenum paymentamt
1 12/2/2014 AB 077LR10 100
2 12/2/2014 AN 077LR10 200
3 12/2/2014 CD 077LR10 300
4 3/10/2015 AN 083LR12 200
5 3/10/2015 WC 083LR12 500
6 5/20/2015 AB 105LR20 200
7 5/20/2015 CD 105LR20 150
8 5/20/2015 RH 105LR20 150
9 5/20/2015 RG 105LR20 400
And I would like to write a query that would bring back the following results:
schedulenum paymentamt
077LR10 600
083LR12 700
105LR20 900
Basically I need to create a SQL statement that selects data from Table A that will result in 2 columns. The first column would be a unique schedule number (i.e., 'schedulenum' - there are multiple rows with the same schedulenum) and a total payment amount ('paymentamt') per schedulenum (each row will have a different 'paymentamt'). I think this would require a self-join but not sure how to do it.
Use a group by when getting sums from one table.
select schedulenum, sum(payment) from mytable
where schedulenum = x
group by schhedulenum
...
select schedulenum, sum(payment) from mytable
group by schhedulenum
order by schedulenum
No self-join needed at all. What you want is the 'group by' keyword and aggregate functions.
SELECT schedulenum, sum(paymentamt)
FROM [TABLE]
GROUP BY schedulenum;
I have a table, which looks like the following:
Table users:
id points date
1 100 2014-07-01
2 500 2014-07-02
3 200 2014-07-01
4 100 2014-07-03
5 100 2014-07-01
6 400 2014-07-02
7 800 2014-07-02
8 200 2014-07-02
Now, how is it possible to select each unique date and count the sum of the points on those days?
So I's need a result something like this:
points date
400 2014-07-01
1900 2014-07-02
100 2014-07-03
SELECT SUM(`points`) AS points, `date`
FROM users
GROUP BY `date`
Try this:
SELECT SUM(points) points, date
FROM users
GROUP BY date
ORDER BY date ASC
This group-and-aggregate operation is a standard query pattern and can be solved following these steps1.
Use a GROUP BY date to aggregate the dates into groups, by date.
Select SUM(points) to tally the points in each aggregated [date] group.
Select the date column, which represents each group, to include it in the results.
Finally, apply ORDER BY date to ensure the results are ordered.
1 It is good etiquette - and results in better answers/discussion - when discussing attempted solutions (ie queries) in questions, and why they didn't work [correctly].