Group rows where there is at least one column with true value - group-by

I have a table like this
+-----+-------------------+------+-------+-------+-------+---+
| Row | email | year | month | flag1 | flag2 | |
+-----+-------------------+------+-------+-------+-------+---+
| 1 | user1#example.com | 2018 | 1 | true | true | |
| 2 | user1#example.com | 2018 | 1 | false | true | |
| 3 | user1#example.com | 2018 | 1 | true | true | |
| 4 | user2#example.com | 2018 | 1 | false | false | |
| 5 | user2#example.com | 2018 | 1 | false | false | |
| 6 | user2#example.com | 2018 | 1 | false | false | |
| 7 | user3#example.com | 2018 | 1 | true | false | |
| 8 | user3#example.com | 2018 | 1 | true | false | |
| 9 | user3#example.com | 2018 | 1 | false | false | |
+-----+-------------------+------+-------+-------+-------+---+
which can be generated with this statement
#standardSQL
WITH table AS (
SELECT "user1#example.com" as email, 2018 as year, 1 as month, TRUE AS flag1, TRUE as flag2
UNION ALL
SELECT "user1#example.com",2018,1,FALSE,TRUE
UNION ALL
SELECT "user1#example.com",2018,1,TRUE,TRUE
UNION ALL
SELECT "user2#example.com",2018,1,FALSE,FALSE
UNION ALL
SELECT "user2#example.com",2018,1,FALSE,FALSE
UNION ALL
SELECT "user2#example.com",2018,1,FALSE,FALSE
UNION ALL
SELECT "user3#example.com",2018,1,TRUE,FALSE
UNION ALL
SELECT "user3#example.com",2018,1,TRUE,FALSE
UNION ALL
SELECT "user3#example.com",2018,1,FALSE,FALSE
)
Grouping by email,year,month, the output table require to have true value (for each of the two flag columns), if in the grouped data there is at least ONE row with true value
The resulting table should be this one
+-----+-------------------+------+-------+-------+-------+---+
| Row | email | year | month | flag1 | flag2 | |
+-----+-------------------+------+-------+-------+-------+---+
| 1 | user1#example.com | 2018 | 1 | true | true | |
| 2 | user2#example.com | 2018 | 1 | false | false | |
| 3 | user3#example.com | 2018 | 1 | true | false | |
+-----+-------------------+------+-------+-------+-------+---+
I started grouping all the flags by the first 3 column, but now I'm now stuck to determine if there is at least one true value inside each array
SELECT email,
year,
month,
ARRAY_AGG(flag1) as flag1,
ARRAY_AGG(flag2) as flag2
FROM table
GROUP BY 1,2,3

#standardSQL
SELECT email,
year,
month,
LOGICAL_OR(flag1) AS flag1,
LOGICAL_OR(flag2) AS flag2
FROM table
GROUP BY 1,2,3

Related

Listing duplicated entities based on two fields with django orm

My objective is getting all orders with duplicated order_number by location, that has checkout = true at least one time. But I'm having issues to translate this to Django ORM.
example of data:
| id | order_number | location_id | checkout |
|----|--------------|-------------|----------|
| 1 | 1 | 1 | true |
| 2 | 1 | 1 | true |
| 3 | 1 | 1 | false |
| 4 | 2 | 1 | true |
| 5 | 1 | 2 | true |
| 6 | 2 | 2 | false |
select count(*), order_number, location_id from orders where checkout = true group by location_id, order_number having count(*) > 1;
the expectation
| count | order_number | location_id |
|-------|--------------|-------------|
| 2 | 1 | 1 |
I already tried this, but it's not working as expected
>>> Order.objects.filter(checkout=True).values_list('order_number', 'location_id').annotate(count_order_number=Count("order_number")).filter(count_order_number__gt=1)
<QuerySet []>
I'm using
Django=3.2
postgresql

View Rows as columns in postgres SQL without using cross Tab as Cross Tab is provioing the excepted results

I am using Postgres 9.6. and i have a result set like this:
employee Name|collegeName | Date |attendance
-------------|------------|----------|-----------
employee1 |college1 |2020-05-01| true
employee1 |college2 |2020-05-01| false
employee2 |college3 |2020-05-01| true
employee3 |college4 |2020-05-02| true
employee4 |college5 |2020-05-02| false
employee5 |college1 |2020-05-03| true
employee6 |college3 |2020-05-03| false
My desired result is as follows:
employee Name|collegeName | 2020-05-01 | 2020-05-02 | 2020-05-03
-------------|------------|------------|------------|-----------
employee1 |college1 | true | |
employee1 | college2 | false | |
employee2 | college3 | true | |
employee3 | college4 | | true |
employee4 |college5 | | false |
employee5 | college1 | | | true
employee6 | college3 | | |false
tried using cross tab but couldn't get the desired Result. please help.

Doctrine GROUPBY with SELECT MAX

Here is my table :
id | place | date | valid
1 | ONE | 10/12/2019 | true
2 | ONE | 11/12/2019 | true
3 | ONE | 12/12/2019 | true
4 | ONE | 13/12/2019 | false
5 | ONE | 14/12/2019 | false
6 | TWO | 10/12/2019 | true
7 | TWO | 11/12/2019 | true
8 | TWO | 12/12/2019 | true
9 | TWO | 13/12/2019 | true
10 | TWO | 14/12/2019 | false
11 | OTH | 10/12/2019 | true
12 | OTH | 11/12/2019 | true
13 | OTH | 12/12/2019 | true
14 | OTH | 13/12/2019 | true
15 | OTH | 14/12/2019 | true
I'm trying with doctrine and the QueryBuilder to get the id's of my table.
I need to get the id's of the MAX date by place where valid is equal to "true".
With the data's displayed, I want to get this result :
3 | ONE | 12/12/2019 | true
9 | TWO | 13/12/2019 | true
15 | OTH | 14/12/2019 | true
I tried some query builder but I can not get the results I wanted.
$qb = $this->createQueryBuilder("o");
$qb->select('o.id, o.place');
$qb->addSelect($qb->expr()->max('o.date').' AS maxDate');
$qb->andWhere($qb->expr()->eq('o.valid', true));
$qb->groupBy('o.place');
I also tried with a subquery but I have a problem to group the place, get the max date and return the ID 3 / 9 and 15.
How can I get the max date and group my lines by place please ?
Thanks

SQL server left join not returning expected records from left table

I have two objects within a SQl Server 2008 R2 database, which I am trying to join together with a left join but I am unable to get the left join to return all records from the table.
1 table - tt_activityoccurrence
1 view - vw_academicweeks
The vw_academicweeks, is a view that contains for each academic year a week number, and the first day and last day of the week and contains 52 records for each academic year.
tt_activityoccurrence is a table which contains occurrences of lessons within a year, lessons will not occur in all 52 weeks of the year.
With my query I am trying to return all instances from the vw_academicweeks view to return the following information
+------------+------------+------------+------------+---------+
| ActivityID | WeekStart | StartTime | EndTime | week_no |
+------------+------------+------------+------------+---------+
| 59936 | 04/09/2017 | 05/09/2017 | 05/09/2017 | 6 |
| 59936 | 11/09/2017 | 12/09/2017 | 12/09/2017 | 7 |
| 59936 | 18/09/2017 | 19/09/2017 | 19/09/2017 | 8 |
| 59936 | 25/09/2017 | 26/09/2017 | 26/09/2017 | 9 |
| 59936 | 02/10/2017 | 03/10/2017 | 03/10/2017 | 10 |
| 59936 | 09/10/2017 | 10/10/2017 | 10/10/2017 | 11 |
| 59936 | 16/10/2017 | 17/10/2017 | 17/10/2017 | 12 |
| 59936 | Null | Null | Null | 13 |
| 59936 | 30/10/2017 | 31/10/2017 | 31/10/2017 | 14 |
| 59936 | 06/11/2017 | 07/11/2017 | 07/11/2017 | 15 |
| 59936 | 13/11/2017 | 14/11/2017 | 14/11/2017 | 16 |
| 59936 | 20/11/2017 | 21/11/2017 | 21/11/2017 | 17 |
| 59936 | 27/11/2017 | 28/11/2017 | 28/11/2017 | 18 |
| 59936 | 04/12/2017 | 05/12/2017 | 05/12/2017 | 19 |
| 59936 | 11/12/2017 | 12/12/2017 | 12/12/2017 | 20 |
| 59936 | 18/12/2017 | 19/12/2017 | 19/12/2017 | 21 |
| 59936 | Null | Null | Null | 22 |
| 59936 | Null | Null | Null | 23 |
+------------+------------+------------+------------+---------+
With the left join I can return all values except the nulls, so that the week_no column is missing rows, 13,22 and 23. I have also tried this with an outer join but receive the same information.
I feel I am missing something obvious but it is escaping me at the moment.
select
ttao.ActivityID
,dateadd(dd,datediff(dd,0,DATEADD(dd, -(DATEPART(dw, ttao.StartTime)-1), ttao.StartTime)),0) WeekStart
,ttao.StartTime
,ttao.EndTime
,aw.week_no
from
vw_AcademicWeeks AW
left join TT_ActivityOccurrence TTAO on
(dateadd(dd,datediff(dd,0,DATEADD(dd, -(DATEPART(dw, ttao.StartTime)-1), ttao.StartTime)),0))=aw.ay_start
where
ay_code='1718' and
TTAO.ActivityID='59936'
order by aw.week_no asc
Your where clause makes it an inner join by eliminating rows outside of the scope of your join. You need to move this logic up to your join statement. Note, I didn't validate your join condiditon (the dateadd...datediff logic)
select
ttao.ActivityID
,dateadd(dd,datediff(dd,0,DATEADD(dd, -(DATEPART(dw, ttao.StartTime)-1), ttao.StartTime)),0) WeekStart
,ttao.StartTime
,ttao.EndTime
,aw.week_no
from
vw_AcademicWeeks AW
left join TT_ActivityOccurrence TTAO on
(dateadd(dd,datediff(dd,0,DATEADD(dd, -(DATEPART(dw, ttao.StartTime)-1), ttao.StartTime)),0)) = aw.ay_start
and ay_code='1718'
and TTAO.ActivityID='59936'
order by aw.week_no asc

Retrieve additional columns on aggregation and date operator

I have the following PostgreSQL table structure, which gathers temperature records for every second:
+----+--------+-------------------------------+---------+
| id | value | date | station |
+----+--------+-------------------------------+---------+
| 1 | 0 | 2017-08-22 14:01:09.314625+02 | 1 |
| 2 | 0 | 2017-08-22 14:01:09.347758+02 | 1 |
| 3 | 25.187 | 2017-08-22 14:01:10.315413+02 | 1 |
| 4 | 24.937 | 2017-08-22 14:01:10.322528+02 | 1 |
| 5 | 25.187 | 2017-08-22 14:01:11.347271+02 | 1 |
| 6 | 24.937 | 2017-08-22 14:01:11.355005+02 | 1 |
| 18 | 24.875 | 2017-08-22 14:01:17.35265+02 | 1 |
| 19 | 25.187 | 2017-08-22 14:01:18.34673+02 | 1 |
| 20 | 24.875 | 2017-08-22 14:01:18.355082+02 | 1 |
| 21 | 25.187 | 2017-08-22 14:01:19.361491+02 | 1 |
| 22 | 24.875 | 2017-08-22 14:01:19.371154+02 | 1 |
| 23 | 25.187 | 2017-08-22 14:01:20.354576+02 | 1 |
| 30 | 24.937 | 2017-08-22 14:01:23.372612+02 | 1 |
| 31 | 0 | 2017-08-22 15:58:53.576238+02 | 1 |
| 32 | 0 | 2017-08-22 15:58:53.590872+02 | 1 |
| 33 | 26.625 | 2017-08-22 15:58:54.59986+02 | 1 |
| 38 | 26.375 | 2017-08-22 15:58:56.593205+02 | 1 |
| 39 | 0 | 2017-08-21 15:59:40.181317+02 | 1 |
| 40 | 0 | 2017-08-21 15:59:40.190221+02 | 1 |
| 41 | 26.562 | 2017-08-21 15:59:41.182622+02 | 1 |
| 42 | 26.375 | 2017-08-21 15:59:41.18905+02 | 1 |
+----+--------+-------------------------------+---------+
I want now to retrieve the maximum value for every hour, along with the data associated to that entry (id, date). As such, I tried the following:
select max(value) as m, (date_trunc('hour', date)) as d
from temperature
where station='1'
group by (date_trunc('hour', date));
Which works fine (fiddle), but I only get the columns m and d as a result. If I now try to add the date or id columns to the SELECT statement, I get the usual column "temperature.id" must appear in the GROUP BY clause or be used in an aggregate function error.
I have already tried approaches such as the ones described here, unfortunately to no avail, as for instance I seem to be unable to perform a join on the date_trunc-generated columns.
The result I am aiming for is this:
+----+--------+-------------------------------+---------+
| id | value | date | station |
+----+--------+-------------------------------+---------+
| 3 | 25.187 | 2017-08-22 14:01:10.315413+02 | 1 |
| 33 | 26.625 | 2017-08-22 15:58:54.59986+02 | 1 |
| 41 | 26.562 | 2017-08-21 15:59:41.182622+02 | 1 |
+----+--------+-------------------------------+---------+
It does not matter which record was retrieved in case two or more entries have the same value.
distinct on:
select distinct on (date_trunc('hour', date)) *
from temperature
where station = '1'
order by date_trunc('hour', date), value desc
Fiddle