I need to pivot the table and get the count for every year present for the respected ids - postgresql

I need to retrieve the data in year wise that is count(values) for year and it should be in format like year and count(values)
select *
from crosstab(select id, year, count(values) from table)
as res(id int, year1 int, year2 int, year3 int, year4 int)
Data in Table
============================
Id | Year | values
============================
1 | 2015-01-10 | 2
1 | 2015-02-11 | 3
1 | 2016-03-11 | 5
1 | 2017-05-07 | 3
1 | 2014-01-01 | 1
2 | 2014-01-10 | 7
2 | 2015-03-03 | 9
2 | 2016-08-08 | 8
2 | 2017-09-09 | 5
Actual Result
===============================
id | 2014 | 2015 | 2016 | 2017
===============================
1 | 1 | 5 | 5 |3
2 | 7 | 9 | 8 |5

Related

postgres tablefunc, sales data grouped by product, with crosstab of months

TIL about tablefunc and crosstab. At first I wanted to "group data by columns" but that doesn't really mean anything.
My product sales look like this
product_id | units | date
-----------------------------------
10 | 1 | 1-1-2018
10 | 2 | 2-2-2018
11 | 3 | 1-1-2018
11 | 10 | 1-2-2018
12 | 1 | 2-1-2018
13 | 10 | 1-1-2018
13 | 10 | 2-2-2018
I would like to produce a table of products with months as columns
product_id | 01-01-2018 | 02-01-2018 | etc.
-----------------------------------
10 | 1 | 2
11 | 13 | 0
12 | 0 | 1
13 | 20 | 0
First I would group by month, then invert and group by product, but I cannot figure out how to do this.
After enabling the tablefunc extension,
SELECT product_id, coalesce("2018-1-1", 0) as "2018-1-1"
, coalesce("2018-2-1", 0) as "2018-2-1"
FROM crosstab(
$$SELECT product_id, date_trunc('month', date)::date as month, sum(units) as units
FROM test
GROUP BY product_id, month
ORDER BY 1$$
, $$VALUES ('2018-1-1'::date), ('2018-2-1')$$
) AS ct (product_id int, "2018-1-1" int, "2018-2-1" int);
yields
| product_id | 2018-1-1 | 2018-2-1 |
|------------+----------+----------|
| 10 | 1 | 2 |
| 11 | 13 | 0 |
| 12 | 0 | 1 |
| 13 | 10 | 10 |

Rank based on row number SQL Server 2008 R2

I want to group rank my table data by rowcount. First 12 rows that are ordered by date for each ProductID would get value = 1. Next 12 rows would get value = 2 assigned and so on.
How table structure looks:
For ProductID = 1267 are below associated dates:
02-01-2016
03-01-2016
.
. (skipping months..table has one date per month)
.
12-01-2016
02-01-2017
.
.
.
02-01-2018
Use row_number() over() with some arithmetic to calculate groups of 12 ordered by date (per productid). Change the sort to ASCendng or DESCendng to suit your need.
select *
, (11 + row_number() over(partition by productid order by somedate DESC)) / 12 as rnk
from mytable
GO
myTableID | productid | somedate | rnk
--------: | :------------- | :------------------ | :--
9 | 123456 | 2018-11-12 08:24:25 | 1
8 | 123456 | 2018-10-02 12:29:04 | 1
7 | 123456 | 2018-09-09 02:39:30 | 1
2 | 123456 | 2018-09-02 08:49:37 | 1
1 | 123456 | 2018-07-04 12:25:06 | 1
5 | 123456 | 2018-06-06 11:38:50 | 1
12 | 123456 | 2018-05-23 21:12:03 | 1
18 | 123456 | 2018-04-02 03:59:16 | 1
3 | 123456 | 2018-01-02 03:42:24 | 1
17 | 123456 | 2017-11-29 03:19:32 | 1
10 | 123456 | 2017-11-10 00:45:41 | 1
13 | 123456 | 2017-11-05 09:53:38 | 1
16 | 123456 | 2017-10-20 15:39:42 | 2
4 | 123456 | 2017-10-14 19:25:30 | 2
20 | 123456 | 2017-09-21 21:31:06 | 2
6 | 123456 | 2017-04-06 22:10:58 | 2
14 | 123456 | 2017-03-24 23:35:52 | 2
19 | 123456 | 2017-01-22 05:07:23 | 2
11 | 123456 | 2016-12-13 19:17:08 | 2
15 | 123456 | 2016-12-02 03:22:32 | 2
dbfiddle here

SQL Select with root parent

I have a table Members(id, name, parent_id), where parent_id is the parent of the member(it is also a member which can have its parent). For example
id | name | parent_id
----------------------
1 | John | NULL
2 | Smith| 1
3 | Andy | 1
4 | Joe | 2
5 | Rick | 2
6 | Craig| 5
7 | Greg | NULL
8 | Bob | 5
9 | Mike | 8
And I'd like to run statement select from members, and I want to have
id | name | parent_id | root_parent_id
--------------------------------------
1 | John | NULL | NULL
2 | Smith| 1 | 1
3 | Andy | 1 | 1
4 | Joe | 2 | 1
5 | Rick | 2 | 1
6 | Craig| 5 | 1
7 | Greg | NULL | NULL
8 | Bob | 7 | 7
9 | Mike | 8 | 7
I want to find the root_parent_id for all members as deeply as possible. Help me please
with recursive recursive_members as (
select *, id root_id, 1 depth
from members
union all
select r.id, r.name, r.parent_id, m.parent_id, r.depth+ 1
from recursive_members r
join members m on r.root_id = m.id
where m.parent_id notnull
)
select distinct on (id) *
from recursive_members
order by id, depth desc;
id | name | parent_id | root_id | depth
----+-------+-----------+---------+-------
1 | John | | 1 | 1
2 | Smith | 1 | 1 | 2
3 | Andy | 1 | 1 | 2
4 | Joe | 2 | 1 | 3
5 | Rick | 2 | 1 | 3
6 | Craig | 5 | 1 | 4
7 | Greg | | 7 | 1
8 | Bob | 5 | 1 | 4
9 | Mike | 8 | 1 | 5
(9 rows)
Read about recursive WITH queries.

sparql getting all months between two dates SPARQL

I am working on a SPARQL query in TopBraid Composer to get the number of data quality rules in each month.
I have a Start Date and End Date, but I need to get all the months between the start date and end date so that I can get a count of the data quality rules applicable to that duration.
My current query and result is as follows-:
SELECT *
WHERE
{
?Rules CDE:Data_Quality_Rule_added_on ?Date1.
?Rules CDE:Data_Quality_Removed_On ?Date2
BIND(month(?Date1) AS ?Month1)
BIND(month(?Date2) AS ?Month2)
BIND(smf:duration("mon",?Date1,?Date2) AS ?dur)
}
LIMIT 5
| [Rules] | Date1 | Date2 | Month1 | Month2 | dur
| CDE:Data_Quality_Rule_13 | 2016-01-28 | 2016-09-15 | 01 | 09 | 8
| CDE:Data_Quality_Rule_16 | 2016-02-29 | 2016-08-08 | 02 | 08 | 5
| CDE:Data_Quality_Rule_18 | 2016-05-15 | 2016-10-31 | 05 | 10 | 6
| CDE:Data_Quality_Rule_4 | 2016-03-28 | 2016-07-02 | 03 | 07 | 3
| CDE:Data_Quality_Rule_5 | 2016-02-02 | 2016-06-06 | 02 | 06 | 4
I am able to get the start month,end month and the duration. But I would like to get all the months between the start month and end month in SPARQL. The end result is to get the month-wise count of the number of data qulaity rules based on the start and end date as follows-:
| Months | Number Of Data Quality Rules |
| 1 | 2
| 2 | 4
| 3 | 6
| 4 | 3
| 5 | 3
| 6 | 4
| 7 | 4
| 8 | 4
| 9 | 5
| 10 | 3
| 11 | 2
| 12 | 5
First, some data to work with that has some rules with begin and end dates:
#prefix : <urn:ex:>
#prefix xsd: <http://www.w3.org/2001/XMLSchema#>
:rule1 :begin "2011-01-10T14:45:13.815-05:00"^^xsd:dateTime ;
:end "2011-06-10T14:45:13.815-05:00"^^xsd:dateTime .
:rule2 :begin "2011-04-10T14:45:13.815-05:00"^^xsd:dateTime ;
:end "2011-10-10T14:45:13.815-05:00"^^xsd:dateTime .
:rule3 :begin "2011-06-10T14:45:13.815-05:00"^^xsd:dateTime ;
:end "2011-11-10T14:45:13.815-05:00"^^xsd:dateTime .
Then you can write a query that gets the months in which each rule is active. IF you then group by the month, and count the number of rules, you get the number of rules active in each month:
prefix : <urn:ex:>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
select ?rule ?month {
#-- Specify the possible values for ?month
#-- in advance. These are just the numbers
#-- one through twelve.
values ?month { 1 2 3 4 5 6 7 8 9 10 11 12 }
#-- Get the begin and end dates of that
#-- you're interested in. The way you
#-- do this depends on the structure of
#-- your data, of course.
?rule :begin ?begin ; :end ?end .
#-- Then take only the values of ?month
#-- that are between the beginning month
#-- and the ending month.
filter ( month(?begin) <= ?month && ?month <= month(?end) )
}
------------------
| rule | month |
==================
| :rule1 | 1 |
| :rule1 | 2 |
| :rule1 | 3 |
| :rule1 | 4 |
| :rule1 | 5 |
| :rule1 | 6 |
| :rule2 | 4 |
| :rule2 | 5 |
| :rule2 | 6 |
| :rule2 | 7 |
| :rule2 | 8 |
| :rule2 | 9 |
| :rule2 | 10 |
| :rule3 | 6 |
| :rule3 | 7 |
| :rule3 | 8 |
| :rule3 | 9 |
| :rule3 | 10 |
| :rule3 | 11 |
------------------
Now you can group those results by month, and then count the number of rules for each month:
prefix : <urn:ex:>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
select ?month (count(distinct ?rule) as ?numRules) where {
values ?month { 1 2 3 4 5 6 7 8 9 10 11 12 }
?rule :begin ?begin ; :end ?end .
filter ( month(?begin) <= ?month && ?month <= month(?end) )
}
group by ?month
--------------------
| month | numRules |
====================
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 3 |
| 7 | 2 |
| 8 | 2 |
| 9 | 2 |
| 10 | 2 |
| 11 | 1 |
--------------------
That doesn't include month 12 in the result, because there were no rules active then. If you want all the months to be listed, you can make the rule matching part optional:
prefix : <urn:ex:>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
select ?month (count(distinct ?rule) as ?numRules) {
values ?month { 1 2 3 4 5 6 7 8 9 10 11 12 }
optional {
?rule :begin ?begin ; :end ?end .
filter ( month(?begin) <= ?month && ?month <= month(?end) )
}
}
group by ?month
--------------------
| month | numRules |
====================
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 3 |
| 7 | 2 |
| 8 | 2 |
| 9 | 2 |
| 10 | 2 |
| 11 | 1 |
| 12 | 0 |
--------------------

Create daily report using crosstabs

I know that crosstabs are just for summaries. But is it possible to use a crosstab for daily reports given two dates? It's more like a details summary.
For example:
Date: 10 August 2012
Start Date: 10/8/2012
End Date: 11/8/2012
Date: 10 August 2012
_________| Center 1 | Center 2 | Total |
Person 1 | 1 | 2 | 3 |
Person 2 | 2 | 5 | 7 |
TOTAL | 3 | 7 | 10 |
Date: 11 August 2012
_________| Center 1 | Center 2 | Total |
Person 1 | 5 | 2 | 7 |
Person 2 | 8 | 5 | 13 |
TOTAL | 13 | 7 | 20 |
Unfortunately, you'd have to have each date as a row in the crosstab, and I think this is the best you'll be able to get:
10 August 2012|_________| Center 1 | Center 2 | Total |
|Person 1 | 1 | 2 | 3 |
|Person 2 | 2 | 5 | 7 |
|TOTAL | 3 | 7 | 10 |
11 August 2012|_________| Center 1 | Center 2 | Total |
|Person 1 | 5 | 2 | 7 |
|Person 2 | 8 | 5 | 13 |
|TOTAL | 13 | 7 | 20 |
|GRAND | 16 | 14 | 30 |
|TOTAL | | | |
So your setup would be:
Center Total
----+--------+-------+------+
Date| | | |
|Person | | |