SQL: Finding averages and grouping by two parameters - mysql

ID Year Month Price
001 1990 JAN 6
001 1990 FEB 8
...
001 1990 DEC 4
001 1991 JAN 7
...
001 2000 DEC 6
002 1990 JAN 7
...
Given a table formatted like the one above, how can you find the average yearly price for each item (of each year)? So for example, I'd like to have a new table that looks like:
ID Year Avg_price
001 1990 7
001 1991 12
...
002 1990 11
...
I've tried the following code:
SELECT ID, Year, AVG(Price)
FROM DATA
GROUP BY ID, Year
But end up getting 0 for each of the averages. The ordering seems to be working correctly though, so I'm not sure why this is. Any help would be greatly appreciated.
EDIT: It turns out there was nothing wrong with my SQL code at all. I guess the answer was simply a bug. Thanks for all your replies, everyone.

Your SQL looks fine to me (Checked with MS SQL).
SQL Fiddle Demo
Please doublecheck with MySQL. ;-)

Related

report server: add to line plot one more line with summa

Would you prompt me, please how to create the additional line on the line chart, which contains sum over all the lines in the chart.
E.g.:
-we have sales over months:
-x-axis is months
-y-axis is sum of sales
On the line chart, we have 3 lines:
-sales on office1
-sales on office2
-sales on office3
On the same chart, I need to add a line with summa of sales over 3 offices.
Thank you.
It depends on what your dataset looks like but the easiest way is usually to do this in your dataset query and supply the 'Total' office numbers in the same manner as the current numbers.
So, if your data looked like this
Office
Month
Amount
Office1
01
1000
Office2
01
1100
Office3
01
1200
Office1
02
1300
Office2
02
1400
Office3
02
1600
Office1
03
1700
Office2
03
1800
Then you could do something simple like
SELECT Office, Month , Amount FROM myTable
UNION ALL
SELECT 'Total', Month, SUM(Amount) from myTable GROUP BY Month
This way "Total" just gets displayed like any other office.

Get records from previous year who has no record this year

I'm creating a monitoring system. Now, I want to get the records from previous year who has no record this year(one table only). How would I do that? Student here :)
sample_tbl
Id name date
1 John 2015
2 Anne 2015
3 John 2016
expected output
Id name date
2 Anne 2015

Vlookup similar in mysql

Let's say I have the table ABC
RENT
- 3 5 6 7 9 10
MONTH
- Jan Mar Jan Jul Dec Feb
How would I go and select the MONTH corresponding to the Minimum Rent?
This is basically performing a MIN operation on the RENT but then I'm completely unaware of how to relate it to the MONTH column and extract the correspondent value.
Can you help?
Supposing you mean a table ABC like this
MONTH RENT
----- ----
Jan 3
Mar 5
Jan 6
Jul 7
Dec 9
Feb 10
Then your SELECT to get minimum rent would be
SELECT MONTH FROM ABC WHERE RENT=(SELECT MIN(RENT) FROM ABC);
When working my MySQL, you need to think about relationships in your database design. Is the month to rent relationship a 1-to-1, 1-to-many, many-to-1, many-to-many?
If you have a relationship that isn't 1-to-1, the best way to implement if is to have 3 tables. A MONTH table, a RENT table, and a table that correlates them.
TABLE_NAME column1 column2
MONTH pkid month
RENT pkid amount
MONTHLY RENT pkid fk_month fk_rent
From here, you can just do a join on the three tables using the correct columns to get the answer you want.

MS Access "double counting" in a query of queries

Apologies if this question is a bit long, but I wanted to explain in detail what it is I am trying to do.
I am developing a database in MS Access 2010/Windows 7 which analyses and reports on incidents (e.g. faults) in an organisation. An incident is reported as beginning at a particular date/time in a particular location for a particular duration. An incident may occasionally cause one or more "live resilience outages" (LRO) which will have the same start-time but can be in different locations and have different durations. So for example a router going out of service in the central technical area for 600 sec might cause live outages of 60 sec and 30 sec in studios 5 and 6 respectively.
I need to report on three date ranges: the month in question, the previous month and the (financial, beginning in April) year to date. So for example the report for March 2012 would consider the periods 01 Mar 2012 - 31 Mar 2012 (month), 01 Feb 2012 - 29 Feb 2012 (previous) and 01 Apr 2011 - 31 Mar 2012 (YTD).
These dates are correctly calculated in a form called ReportCentre. I have three queries to return the LROs for the different date ranges: QueryLROMonth, QueryLROPrevious and QueryLROYTD all of which work properly in isolation (i.e. return the correct values). So for example QueryLROMonth is defined as
SELECT lro.*
FROM lro INNER JOIN incidents ON lro.pid = incidents.id
WHERE (((incidents.begin) Between [Forms]![ReportCentre].[StartMonth] And
[Forms]![ReportCentre].[EndMonth]));
which returns the expected values:
id pid duration facility
6 681 30 23
7 686 857 23
8 735 600 25
9 738 600 25
as does the YTD query
id pid duration facility
1 100 120 25
2 366 5 25
3 380 460 1
4 505 341 23
5 622 0 29
6 681 30 23
7 686 857 23
8 735 600 25
9 738 600 25
20 1297 50 1
So far so good, but now the bit that's got me puzzled. I am trying to design another query which takes the output of the three LRO queries (and some other data), groups it all by facility and calculates things like availability. If I design a totals query and include the Facilities table (for the facility name) and the QueryLROMonth query e.g.
SELECT facilities.facility, Count(QueryLROMonth.id) AS lrocountmonth, Sum(QueryLROMonth.duration) AS lrosecondsmonth
FROM QueryLROMonth INNER JOIN facilities ON QueryLROMonth.facility = facilities.ID
GROUP BY facilities.facility;
This works fine and produces what I expect.
facility lrocountmonth lrosecondsmonth
HQ3 2 887
HQ5 2 1200
but as soon as I introduce the YTD query:
SELECT facilities.facility, Count(QueryLROMonth.id) AS lrocountmonth, Sum(QueryLROMonth.duration) AS lrosecondsmonth, Count(QueryLROYTD.id) AS lrocountytd, Sum(QueryLROYTD.duration) AS lrosecondsytd
FROM QueryLROYTD INNER JOIN (QueryLROMonth INNER JOIN facilities ON QueryLROMonth.facility = facilities.ID) ON QueryLROYTD.facility = facilities.ID
GROUP BY facilities.facility;
for some reason stuff starts being counted reported wrongly. Specifically the two Count columns are multiplied together and so lrocountmonth and lrosecondsmonth are both multiplied by lrocountytd. Similarly lrocountytd and lrosecondsytd are both multiplied by lrocountmonth.
facility lrocountmonth lrosecondsmonth lrocountytd lrosecondsytd
HQ3 6 2661 6 2456
HQ5 8 4800 8 2650
What am I doing wrong? How do I prevent this entanglement?
Your [QueryLROMonth] and [QueryLROYTD] queries each return multiple rows per Facility, but because you are effectively JOINing them on just the Facility_ID you are producing an OUTER JOIN of sorts. For example, if for a given Facility your [Month] query contains 3 rows and your [YTD] query contains 6 rows then your JOIN on Facility_ID alone will produce 18 rows.
You'll want to create aggregation queries that "roll up" the Monthly and YTD numbers by Facility first, so they each have only one row per Facility. You can then use them in your final query to produce the report.
Troubleshooting tip: If your aggregation queries are producing strange results try removing the GROUP BY parts so you can see the underlying rows that are being aggregated.

help with mysql select query

what I'm trying to do:
from these tables
---------------------------------
name date state
---------------------------------
ali jan 12 started
ali jan 12 drop out
masa jan 12 registered
masa jan 12 started
sami jan 12 started
I want the results to be
---------------------------------
name date state
---------------------------------
masa jan 12 started
sami jan 12 started
So basically what i want is to have all the started users without the ones who dropped out
so the filtering should be based on the state
thanks
Those two rows in your result example are not the only started people on that date.
SELECT * FROM table WHERE state = 'started';
Would return 3 rows:
---------------------------------
name date state
---------------------------------
ali jan 12 started
masa jan 12 started
sami jan 12 started
To get the two rows in your example you need:
SELECT * FROM table WHERE name IN ('sami', 'mesa');
Update, added this example
You could limit if you only wanted two rows:
SELECT * FROM table WHERE state = 'started' LIMIT 2;
Perhaps something along the following lines is what you need...
SELECT NAME,
DATE,
STATE
FROM MYTAB
WHERE STATE = 'Started' AND
NOT EXISTS (SELECT *
FROM MYTAB MYTAB2
WHERE MYTAB2.NAME = MYTAB.NAME AND
MYTAB2.STATE = 'Drop Out');
That should get everyone who started and didn't drop out.
SELECT name, date, state FROM table GROUP BY name HAVING state = 'started';
I believe this would eliminate people who dropped out eventually because the GROUP BY would put the people with the same name into the same group, and then eliminate them once they drop out with the HAVING statement.
select * from table where state != 'dropped out'