Select Max() and Min() date and Sum up quantity - sql

I have table with data as below
StartDate EndDate ID Qty
2017-09-01 2017-10-01 PJFC1000205 1
2017-10-01 2017-11-01 PJFC1000205 2
2017-11-01 2017-12-01 PJFC1000205 3
2017-12-01 2018-01-01 PJFC1000205 4
I wish sum up the qty and wish the output as below
StartDate EndDate ID Qty
2017-09-01 2018-01-01 PJFC1000205 10
Is it possible to do so? How I can do it?
I'm using MSSQL 2014.
Please guide me, thanks.

Using the group by on ID and aggregate functions on the other fields should do the trick.
SELECT min(Start_Date), max(End_Date), ID, sum(Qty)
FROM table
GROUP BY ID;

Related

Select to search column on group by query

I have one table called prices that have a reference from table products through product_id column. I want a query that selects prices grouped by product_id with the max final date and get the value of start_date through one select with id of price grouped.
I try with the following query but I am getting a wrong value of start date. Is weird because of the result subquery return more than one row even though I use the price id on where clause. Because that I put the limit on the query but it is wrong.
select prices.produto_id, prices.id,
MAX(CASE WHEN prices.finish_date IS NULL THEN COALESCE(prices.finish_date,'9999-12-31') ELSE prices.finish_date END) as finish_date,
(select start_date from prices where prices.id = prices.id limit 1)
as start_date from prices group by prices.product_id, prices.id
How I can get the relative start date of the price id in my grouped row? I am using postgresql.
A example to view what I want with my query:
DataSet:
ID | PRODUCT_ID | START_DATE | FINISH_DATE
1 1689 2018-01-19 02:00:00 2019-11-19 23:59:59
2 1689 2019-10-11 03:00:00 2019-10-15 23:59:59
3 1689 2019-01-11 03:00:00 2019-05-15 23:59:59
4 1690 2019-11-11 03:00:00 2019-12-15 23:59:59
5 1690 2019-05-11 03:00:00 2025-12-15 23:59:59
6 1691 2019-05-11 03:00:00 null
I want this result:
ID | PRODUCT_ID | START_DATE | FINISH_DATE
1 1689 2018-01-19 02:00:00 2019-11-19 23:59:59
5 1690 2019-05-11 03:00:00 2025-12-15 23:59:59
6 1691 2019-05-11 03:00:00 9999-12-31 23:59:59
The start date should be the same value of the row before the group by.
I would recommend DISTINCT ON in Postgres:
select distinct on (p.product_id) p.*
from prices p
order by p.product_id,
p.finish_date desc nulls first;
NULL values are treated as larger than any other value, so a descending sort puts them first. However, I've included nulls first just to be explicit.
DISTINCT ON is a very handy Postgres extension, which you can learn more about in the documentation.
Try this
with data as (
SELECT id, product_id,
max(COALESCE(finish_date,'9999-12-31')) as finish_date from prices group by 1,2)
select d.*, p.start_date from data d join prices p on p.id = d.id;
It surely isnt' the most elegant solution, but it should work.

How to filter only a subset of data while maintain existing records as is in a table?

[SQL Novice] I have a table that looks like this:
id date
1 2019-01-01
1 2019-01-02
2 2019-03-01
2 2019-05-01
I want to only filter the id column on 2 where date is between 2019-04-01 and 2019-05-01 without impacting id equals 1.
The new table should look like this:
id date
1 2019-01-01
1 2019-01-02
2 2019-03-01
I tried this:
select * from table1 where id =2 and date between 2019-03-01 and 2019-04-01
And get this data set:
id date
2 2019-03-01
I think you want or:
where id = 1 or
(id = 2 and date between '2019-03-01' and '2019-04-01')
for your desired result need
select * from table1 where [date] >= '2019-01-01' and [date] <= '2019-03-01'

Specific group by latest date in SQL Server

I want to run a SQL query on the following set of data
date creation_date value
------------------------------------
2018-01-01 2017-05-05 1
2018-01-02 2017-05-05 0
2018-01-03 2017-05-05 1
2018-01-04 2017-05-05 0
2018-01-05 2017-05-05 1
2018-01-06 2017-05-05 1
2018-01-02 2017-05-11 5
I want to get the following results
2018-01-01 2017-05-05 1
2018-01-02 2017-05-11 5
2018-01-03 2017-05-05 1
2018-01-04 2017-05-05 0
2018-01-05 2017-05-05 1
2018-01-06 2017-05-05 1
Basically I want to get all the dates, group it by dates and get the latest creation date and get the value for that creation date.
I tried
select date, max(Creation_date), value
from datasource
group by date, blocked
but that doesn't do it.
I think you can use query like this:
select *
from (
select *
, row_number() over (partition by date, blocked order by creation_date desc) seq
from datasource) t
where t.seq = 1;
SQL Server Fiddle Demo
Try to use subquery and join with it
SELECT d.*
FROM datasource d
JOIN
(
SELECT [date],MAX(Creation_date) LastCreationDate
FROM datasource
GROUP BY [date]
) l
ON d.[date]=l.[date] AND d.Creation_date=l.LastCreationDate
Or the second variant if Creation_date is common for all the [date]
SELECT *
FROM datasource
WHERE Creation_date=(SELECT MAX(Creation_date) FROM datasource)

From hourly data to daily data using SQL GROUP BY

I have a table like this:
fld_id fld_DateTime fld_Index
2017-07-01 00:00:00.000 5
2017-07-01 01:00:00.000 10
2017-07-01 02:00:00.000 15
2017-07-01 03:00:00.000 40
...........
...........
2017-07-01 23:00:00.000 70
2017-07-02 00:00:00.000 110
2017-07-02 01:00:00.000 140
2017-07-02 02:00:00.000 190
...............
...............
2017-07-02 23:00:00.000 190
What I am trying to do is to group them and count sum of fld_index per day like so:
fld_id fld_DateTime SUM
2017-07-01 190
2017-07-02 400
Here's what I've tried:
SELECT fld_dateTime, SUM(fld_Index) AS Sum
FROM tbl_data
WHERE
AND fld_ConsDateTime BETWEEN '2017-07-01' AND '2017-08-02'
GROUP BY fld_dateTime
It calculates the sum but still in hourly format. How to achieve the daily format like above example?
UPDATE Monthly Part Output
2017 8 30630800.0000
2017 7 589076201.1800
Simply cast as DATE
SELECT CAST(fld_dateTime AS DATE) AS fld_Date, SUM(fld_Index) AS Sum
FROM tbl_data
WHERE
fld_ConsDateTime BETWEEN '2017-07-01' AND '2017-08-02'
GROUP BY CAST(fld_dateTime AS DATE);
EDIT:
What about month? Is it the same logic?
It depends on your RDBMS, but in SQL Server you could use:
SELECT YEAR(fld_dateTime), MONTH(fld_dateTime), SUM(fld_Index) AS Sum
FROM tbl_data
GROUP BY YEAR(fld_dateTime), MONTH(fld_dateTime);
It is important to add year part to avoid grouping records from different years.
You need to extract the date. In SQL Server, you would do:
SELECT CAST(fld_dateTime as DATE) as fld_date, SUM(fld_Index) AS Sum
FROM tbl_data
WHERE fld_ConsDateTime >= '2017-07-01' AND
fld_ConsDateTime < '2017-08-03'
GROUP BY CAST(fld_dateTime as DATE)
ORDER BY fld_date
In MySQL, the above would work, but I would do:
SELECT DATE(fld_dateTime) as fld_date, SUM(fld_Index) AS Sum
FROM tbl_data
WHERE fld_ConsDateTime >= '2017-07-01' AND
fld_ConsDateTime < '2017-08-03'
GROUP BY DATE(fld_dateTime)
ORDER BY fld_date;
In both cases, you should change the WHERE clause. Your version would keep flights where the date/time is exactly midnight on 2017-08-02. Using >= and < is more accurate -- taking all date/times on one day but not the next.

Select min/max from group defined by one column as subgroup of another - SQL, HPVertica

I'm trying to find the min and max date within a subgroup of another group. Here's example 'data'
ID Type Date
1 A 7/1/2015
1 B 1/1/2015
1 A 8/5/2014
22 B 3/1/2015
22 B 9/1/2014
333 A 8/1/2015
333 B 4/1/2015
333 B 3/29/2014
333 B 2/28/2013
333 C 1/1/2013
What I'd like to identify is - within an ID, what is the min/max Date for each block of similar Type? So for ID # 333 I want the below info:
A: min & max = 8/1/2015
B: min = 2/28/2013
max = 4/1/2015
C: min & max = 1/1/2013
I'm having trouble figuring out how to identify only uninterrupted groupings of Type within a grouping of ID. For ID #1, I need to keep the two 'A' Types with separate min/max dates because they were split by a Type 'B', so I can't just pull the min date of all Type A's for ID #1, it has to be two separate instances.
What I've tried is something like the below two lines, but neither of these accurately captures the case mentioned above for ID #1 where Type B interrupts Type A.
Max(Date) OVER (Partition By ID, Type)
or this:
Row_Number() OVER (Partition By ID, Type ORDER BY Date DESC)
,then selecting Row #1 for max date, and date ASC w/ row #1 for min date
Thank you for any insight you can provide!
If I understand right, you want the min/max values for an id/type grouped using a descending date sort, but the catch is that you want them based on clusters within the id by time.
What you can do is use CONDITIONAL_CHANGE_EVENT to tag the rows on change of type, then use that in your GROUP BY on a standard min/max aggregation.
This would be the intermediate step towards getting to what you want:
select ID, Type, Date,
CONDITIONAL_CHANGE_EVENT(Type) OVER( PARTITION BY ID ORDER BY Date desc) cce
from mytable
group by ID, Type, Date
order by ID, Date desc, Type
ID Type Date cce
1 A 2015-07-01 00:00:00 0
1 B 2015-01-01 00:00:00 1
1 A 2014-08-05 00:00:00 2
22 B 2015-03-01 00:00:00 0
22 B 2014-09-01 00:00:00 0
333 A 2015-08-01 00:00:00 0
333 B 2015-04-01 00:00:00 1
333 B 2014-03-29 00:00:00 1
333 B 2013-02-28 00:00:00 1
333 C 2013-01-01 00:00:00 2
Once you have them grouped using CCE, you can do an aggregate on this to get the min/max you are looking for grouping on cce. You can play with the order by at the bottom, this ordering seem to make the most sense to me.
select id, type, min(date), max(date)
from (
select ID, Type, Date,
CONDITIONAL_CHANGE_EVENT(Type) OVER( PARTITION BY ID ORDER BY Date desc) cce
from mytable
group by ID, Type, Date
) x
group by id, type, cce
order by id, 3 desc, 4 desc;
id type min max
1 A 2015-07-01 00:00:00 2015-07-01 00:00:00
1 B 2015-01-01 00:00:00 2015-01-01 00:00:00
1 A 2014-08-05 00:00:00 2014-08-05 00:00:00
22 B 2014-09-01 00:00:00 2015-03-01 00:00:00
333 A 2015-08-01 00:00:00 2015-08-01 00:00:00
333 B 2013-02-28 00:00:00 2015-04-01 00:00:00
333 C 2013-01-01 00:00:00 2013-01-01 00:00:00