Select and Count Multiple Group By SQL - sql

Can someone tell me how to do this in Database?
I've tried some sql like:
SELECT disastertype, YEAR(eventdate) as year,
COUNT(disastertype) AS disastertype_total
FROM v_disasterlogs_all
WHERE YEAR(eventdate) >= year(CURRENT_TIMESTAMP) - 4
GROUP BY YEAR(eventdate)
ORDER BY YEAR(eventdate) ASC
But, it only shows like this:

include disastertype on our group by statement.
SELECT disastertype, YEAR(eventdate) as year,
COUNT(disastertype) AS disastertype_total
FROM v_disasterlogs_all
WHERE YEAR(eventdate) >= year(CURRENT_TIMESTAMP) - 4
GROUP BY YEAR(eventdate), disastertype
ORDER BY YEAR(eventdate) ASC

I am assuming you want a count (the column index) to be associated with each unique year?
In this case, a possible solution in postgres will be as below.
select
dense_rank() over (order by date_part('year', (eventdate))) as index ,
date_part('year', (eventdate)) as year,
disastertype,
count(disastertype)
from
v_disaterlogs_all
where
date_part('year', (eventdate)) >= date_part('year', now()) - 4
group by
year,
disastertype
order by
year asc;
In postgres, I have used the function date_part to extract the year from the timestamp.
Working solution on dbfiddle.

Related

SQL query for multiple values of a column

I have db with names etc with date of birth. How can I get count of columns for all 12 months of the dates?
Exact code depends on the database you use; you should, somehow, "extract" month from date of birth in order to GROUP BY it.
In Oracle, you might have done it as
select to_char(date_of_birth), 'mon') dob_month,
count(*)
from your_table
group by to_char(date_of_birth, 'mon');
or
select extract(month from date_of_birth) dob_month,
count(*)
from your_table
group by extract(month from date_of_birth);

data function grouped item in a subquery

I'm using Postgresql to write a query which for every day calculate the sum of diff values and get unit price from other table il_costs, what I try to achieve with a subquery. Below whole query:
SELECT date(read.readed_at),
SUM(read.diff),
(SELECT water_unit
FROM il_costs
WHERE EXTRACT(MONTH FROM created_at) = EXTRACT(MONTH FROM date(read.readed_at))
AND EXTRACT(YEAR FROM created_at) = EXTRACT(YEAR FROM date(read.readed_at)))
FROM il_communicators_readings read
GROUP BY date(read.readed_at)
ORDER BY date(read.readed_at) ASC;
I'm getting error about ungrouped column, but I'm using date(read.readed_at) also in grouped function:
ERROR: subquery uses ungrouped column "read.readed_at" from outer query
LINE 1: ...(MONTH FROM created_at) = EXTRACT(MONTH FROM date(read.reade...
You can try using your query as a subquery and perform the correlated subquery in the outer query:
SELECT mydate, s_diff,
(SELECT water_unit
FROM il_costs
WHERE EXTRACT(MONTH FROM created_at) = EXTRACT(MONTH FROM mydate)
AND EXTRACT(YEAR FROM created_at) = EXTRACT(YEAR FROM mydate))
FROM (
SELECT date(read.readed_at) AS mydate,
SUM(read.diff) as s_diff
FROM il_communicators_readings read
GROUP BY date(read.readed_at) ) AS t
ORDER BY mydate ASC;
the problem is not read.readed_at, it's the subquery not in the group by. and i don't think it's a good idea to use subquery like this.
Try this:
SELECT date(read.readed_at),
SUM(read.diff),
costs.water_unit
FROM il_communicators_readings read
Left Join il_costs costs
ON EXTRACT(MONTH FROM costs.created_at) = EXTRACT(MONTH FROM date(read.readed_at))
AND EXTRACT(YEAR FROM costs.created_at) = EXTRACT(YEAR FROM date(read.readed_at))
GROUP BY date(read.readed_at),costs.water_unit
ORDER BY date(read.readed_at) ASC;

order by month oracle

I'm trying to make a simple query to find the average car sales per month from a table called "salestransaction".
My code:
select to_char(st.dateofsale, 'MON') as mnth, count(*) / 2 as Average_Car_Sales
from salestransaction st
group by to_char(st.dateofsale, 'MON')
order by to_char(st.dateofsale, 'MON');
My order by month is not outputting the correct order.
What can I do to make it output by month? starting from JAN - DEC?
Thank you.
An easy approach is to add month number to group by, then order by this field:
select to_char(st.dateofsale, 'MON') as mnth,
count(*) / 2 as Average_Car_Sales
from salestransaction st
group by EXTRACT(month FROM st.dateofsale),
to_char(st.dateofsale, 'MON')
order by EXTRACT(month FROM st.dateofsale);
If you try to order without aggregate function or without adding month number in group by expression then you will get ORA-00979: not a GROUP BY expression error
To avoid Extract you can use to_char with MM pattern:
select to_char(st.dateofsale, 'MON') as mnth,
count(*) / 2 as Average_Car_Sales
from salestransaction st
group by to_char(st.dateofsale, 'MM'),
to_char(st.dateofsale, 'MON')
order by to_char(st.dateofsale, 'MM');
My recommendation:
order by min(st.dateofsale);
That is, just pull a value out for each group and use that for the ordering.
If you have data from multiple years, the above might not work. Instead:
order by min(extract(month from st.dateofsale))
It is because you order them according to the month name in this case, december comes before january. You need to get their numeric values.
Here is an example from oracle documantation:
SELECT EXTRACT(month FROM order_date) "Month",
COUNT(order_date) "No. of Orders"
FROM orders
GROUP BY EXTRACT(month FROM order_date)
ORDER BY EXTRACT(month FROM order_date)
You can check it from this link for more detailed information:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions050.htm

sql to find row for min date in each month

I have a table, lets say "Records" with structure:
id date
-- ----
1 2012-08-30
2 2012-08-29
3 2012-07-25
I need to write an SQL query in PostgreSQL to get record_id for MIN date in each month.
month record_id
----- ---------
8 2
7 3
as we see 2012-08-29 < 2012-08-30 and it is 8 month, so we should show record_id = 2
I tried something like this,
SELECT
EXTRACT(MONTH FROM date) as month,
record_id,
MIN(date)
FROM Records
GROUP BY 1,2
but it shows 3 records.
Can anybody help?
SELECT DISTINCT ON (EXTRACT(MONTH FROM date))
id,
date
FROM Records1
ORDER BY EXTRACT(MONTH FROM date),date
SQLFiddle http://sqlfiddle.com/#!12/76ca2/3
UPD: This query:
1) Orders the records by month and date
2) For every month picks the first record (the first record has MIN(date) because of ordering)
Details here http://www.postgresql.org/docs/current/static/sql-select.html#SQL-DISTINCT
This will return multiples if you have duplicate minimum dates:
Select
minbymonth.Month,
r.record_id
From (
Select
Extract(Month From date) As Month,
Min(date) As Date
From
records
Group By
Extract(Month From date)
) minbymonth
Inner Join
records r
On minbymonth.date = r.date
Order By
1;
Or if you have CTEs
With MinByMonth As (
Select
Extract(Month From date) As Month,
Min(date) As Date
From
records
Group By
Extract(Month From date)
)
Select
m.Month,
r.record_id
From
MinByMonth m
Inner Join
Records r
On m.date = r.date
Order By
1;
http://sqlfiddle.com/#!1/2a054/3
select extract(month from date)
, record_id
, date
from
(
select
record_id
, date
, rank() over (partition by extract(month from date) order by date asc) r
from records
) x
where r=1
order by date
SQL Fiddle
select distinct on (date_trunc('month', date))
date_trunc('month', date) as month,
id,
date
from records
order by 1, 3 desc
I think you need use sub-query, something like this:
SELECT
EXTRACT(MONTH FROM r.date) as month,
r.record_id
FROM Records as r
INNER JOIN (
SELECT
EXTRACT(MONTH FROM date) as month,
MIN(date) as mindate
FROM Records
GROUP BY EXTRACT(MONTH FROM date)
) as sub on EXTRACT(MONTH FROM r.date) = sub.month and r.date = sub.mindate

Month statistics

I have a table in Postgres and MySQL with a 'created_at' column. I would like to query it for the following:
Month Count
1 0
2 0
3 0
4 12
5 15
...
Can anyone cough up some sql? Notice that the months with no rows returned must be listed as 0's. I have this:
SELECT month(created_at) as month, count(*) as c
FROM `sale_registrations`
WHERE (created_at>='2011-01-01' and created_at<='2011-12-31')
GROUP BY month(created_at)
ORDER BY month(created_at)
Use EXTRACT(month FROM created_at) to get the month. This works in MySQL as well.
Edit: Use a RIGHT JOIN on a table with the month numbers:
CREATE TABLE months(nr tinyint);
INSERT INTO months(nr) VALUES (1),(3),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12);
SELECT
nr as month,
COUNT(*) as c
FROM
sale_registrations
RIGHT JOIN months ON EXTRACT(month FROM created_at) = nr
WHERE
(created_at BETWEEN '2011-01-01' AND '2011-12-31')
GROUP BY
EXTRACT(month FROM created_at)
ORDER BY
EXTRACT(month FROM created_at) ASC;
In PostgreSQL you could use generate_series(), but that's not going to work in MySQL.