How to order the result of ROLLUP by each groups total - postgresql

So I have the following query that produces the following result:
actname | year | tickets
---------------+----------+---------
Join Division | 2016 | 2
Join Division | 2018 | 2
Join Division | 2020 | 3
Join Division | Total | 7 <<<
QLS | 2018 | 2
QLS | 2019 | 1
QLS | Total | 3 <<<
Scalar Swift | 2017 | 3
Scalar Swift | 2018 | 1
Scalar Swift | 2019 | 1
Scalar Swift | Total | 5 <<<
The Selecter | 2017 | 4
The Selecter | 2018 | 4
The Selecter | Total | 8 <<<
The Where | 2016 | 1
The Where | 2017 | 3
The Where | 2018 | 5
The Where | 2020 | 4
The Where | Total | 13 <<<
ViewBee 40 | 2017 | 3
ViewBee 40 | 2018 | 1
ViewBee 40 | Total | 4 <<<
The problem I have is that I want to re-order the results such that the group with the lowest Total occurs first, such that the results would look like this:
actname | year | tickets
---------------+----------+---------
QLS | 2018 | 2
QLS | 2019 | 1
QLS | Total | 3 <<<
ViewBee 40 | 2017 | 3
ViewBee 40 | 2018 | 1
ViewBee 40 | Total | 4 <<<
Scalar Swift | 2017 | 3
Scalar Swift | 2018 | 1
Scalar Swift | 2019 | 1
Scalar Swift | Total | 5 <<<
Join Division | 2016 | 2
Join Division | 2018 | 2
Join Division | 2020 | 3
Join Division | Total | 7 <<<
The Selecter | 2017 | 4
The Selecter | 2018 | 4
The Selecter | Total | 8 <<<
The Where | 2016 | 1
The Where | 2017 | 3
The Where | 2018 | 5
The Where | 2020 | 4
The Where | Total | 13 <<<
I'm obtaining the results by using the following GROUP:
GROUP BY actname, ROLLUP(year)
Which is combining all the ticket amounts of the same actname and year together.
I can provide the full query if necessary!
Thanks

Using window function (which is sum() in this case) you can set value to groups (groups are partitioned by actname column) , so now every group from actname column, have same value, as its own row where year='Total'.
Then simply sort by that new column, something like this:
with t(actname, year, tickets) as (
VALUES
('Join Division','2016',2),
('Join Division','2018',2),
('Join Division','2020',3),
('Join Division','Total',7),
('QLS','2018',2),
('QLS','2019',1),
('QLS','Total',3 ),
('Scalar Swift','2017',3),
('Scalar Swift','2018',1),
('Scalar Swift','2019',1),
('Scalar Swift','Total',5 ),
('The Selecter','2017',4),
('The Selecter','2018',4),
('The Selecter','Total',8 ),
('The Where','2016',1),
('The Where','2017',3),
('The Where','2018',5),
('The Where','2020',4),
('The Where','Total',13 ),
('ViewBee 40','2017',3),
('ViewBee 40','2018',1),
('ViewBee 40','Total',4 )
)
SELECT * FROM (
select *, sum(case when year = 'Total' then tickets end) over(partition by actname) sm from t
) tt
ORDER BY sm, year

Related

PostgreSQL Query Using Crosstab

Now, I am leaning postgreSQL. In the study, I found crosstab in postgreSQL. I tried to apply this function to my customized table, but it dose not work. please help!!
This is my Table
year | type | count
------+----------+----
2015 | AS | 6
2015 | HY | 6
2015 | KR | 6
2015 | SE | 6
2016 | AS | 2
2016 | HY | 2
2016 | KR | 2
2016 | SE | 2
2017 | AS | 1
2017 | HY | 1
2017 | KR | 1
2017 | SE | 1
2018 | AS | 2
2018 | HY | 2
2018 | KR | 2
2018 | SE | 2
I want to change this table like this
year | AS | HY | KR | SE |
----------------------------------
2015 | 6 | 6 | 6 | 6 |
2016 | 2 | 2 | 2 | 2 |
2017 | 1 | 1 | 1 | 1 |
2018 | 2 | 2 | 2 | 2 |
To make that table, I designed query using crosstab, but dose not work!
Please Let me know the query of this problem.
You could achieve this without Crosstab, you can use Aggregate function.
Query :
select
year,
max(counts) filter (where type = 'AS') as "AS",
max(counts) filter (where type = 'HY') as "HY",
max(counts) filter (where type = 'KR') as "KR",
max(counts) filter (where type = 'SE') as "SE"
from
tbl
group by
year
order by
year asc
Demo <> DB Fiddle
And if you are try learning Crosstab this answer are really great and explain really well about to do pivot use Crosstab.
PostgreSQL Crosstab Query

Calculate LAG variable after filtering in Tableau

I have a dataset with 4 columns: ID (unique identifier of user), Year, Country and Level in this format:
+----+------+---------+-------+
| ID | Year | Country | Level |
+----+------+---------+-------+
| 1 | 2015 | USA | 1 |
| 1 | 2016 | China | 2 |
| 2 | 2015 | China | 2 |
| 2 | 2016 | Russia | 2 |
| 3 | 2015 | Russia | 1 |
| 3 | 2016 | China | 2 |
| 4 | 2015 | USA | 2 |
| 4 | 2016 | USA | 3 |
| 5 | 2014 | China | 1 |
| 5 | 2016 | USA | 2 |
| 6 | 2015 | USA | 1 |
| 6 | 2016 | USA | 2 |
| 7 | 2015 | Russia | 2 |
| 7 | 2016 | China | 3 |
+----+------+---------+-------+
The user will be able to filter the dataset by country.
I want to create a table using the country filter that shows in a column if a user was the previous year in any of the countries selected aggregated by the level variable, apart from other variables only affected by the current country filter.
For example E.g., if I select China and USA:
+----+------+---------+-------+-----------------+
| ID | Year | Country | Level | In selection PY |
+----+------+---------+-------+-----------------+
| 1 | 2015 | USA | 1 | No |
| 1 | 2016 | China | 2 | Yes |
| 2 | 2015 | China | 2 | No |
| 3 | 2016 | China | 2 | No |
| 4 | 2015 | USA | 2 | No |
| 4 | 2016 | USA | 3 | Yes |
| 5 | 2014 | China | 1 | No |
| 5 | 2016 | USA | 2 | No |
| 6 | 2015 | USA | 1 | No |
| 6 | 2016 | USA | 2 | Yes |
| 7 | 2016 | China | 3 | No |
+----+------+---------+-------+-----------------+
The aggregated result will be:
+-------+-------------------+-----------------+
| Level | Number of records | In selection PY |
+-------+-------------------+-----------------+
| 1 | 3 | 0 |
| 2 | 6 | 2 |
| 3 | 2 | 1 |
+-------+-------------------+-----------------+
Do you know any way to calculate this aggregated table efficiently? (this would be done in a dataset with millions of rows, with a variable set of countries to be selected)
I found a solution, will post in case it is helpful for someone else:
I change the Country filter to "Add to Context" and created this variable:
In Selection PY: if Year = 2016 then
{fixed [ID]:min(if Year = 2015 then 1 END)}
elseif Year = 2015 then
{fixed [ID]:min(if Year = 2014 then 1 END)}
elseif Year = 2014 then
{fixed [ID]:min(if Year = 2013 then 1 END)}
In this way the variable Selection PY is dynamically calculated according to the country filter.
It is only necessary to know in advance which years are stored in the dataset (or add more years to be safe).

Is it possible to do mathematical operations on values in the same column but different rows?

Say I have this table,
year | name | score
------+---------------+----------
2017 | BRAD | 5
2017 | BOB | 5
2016 | JON | 6
2016 | GUYTA | 2
2015 | PAC | 2
2015 | ZAC | 0
How would I go about averaging the scores by year and then getting the difference between years?
year | increase
------+-----------
2017 | 1
2016 | 3
You should use a window function, lead() in this case:
select year, avg, (avg - lead(avg) over w)::int as increase
from (
select year, avg(score)::int
from my_table
group by 1
) s
window w as (order by year desc);
year | avg | increase
------+-----+----------
2017 | 5 | 1
2016 | 4 | 3
2015 | 1 |
(3 rows)

Symfony2 Query to find last working date from Holiday Calender

I had a calender entity in my project which manages the open and close time of business day of the whole year.
Below is the record of a specific month
id | today_date | year | month_of_year | day_of_month | is_business_day
-------+---------------------+------+---------------+-------------+---------------+
10103 | 2016-02-01 00:00:00 | 2016 | 2 | 1 | t
10104 | 2016-02-02 00:00:00 | 2016 | 2 | 2 | t
10105 | 2016-02-03 00:00:00 | 2016 | 2 | 3 | t
10106 | 2016-02-04 00:00:00 | 2016 | 2 | 4 | t
10107 | 2016-02-05 00:00:00 | 2016 | 2 | 5 | t
10108 | 2016-02-06 00:00:00 | 2016 | 2 | 6 | f
10109 | 2016-02-07 00:00:00 | 2016 | 2 | 7 | f
10110 | 2016-02-08 00:00:00 | 2016 | 2 | 8 | t
10111 | 2016-02-09 00:00:00 | 2016 | 2 | 9 | t
10112 | 2016-02-10 00:00:00 | 2016 | 2 | 10 | t
10113 | 2016-02-11 00:00:00 | 2016 | 2 | 11 | t
10114 | 2016-02-12 00:00:00 | 2016 | 2 | 12 | t
10115 | 2016-02-13 00:00:00 | 2016 | 2 | 13 | f
10116 | 2016-02-14 00:00:00 | 2016 | 2 | 14 | f
10117 | 2016-02-15 00:00:00 | 2016 | 2 | 15 | t
10118 | 2016-02-16 00:00:00 | 2016 | 2 | 16 | t
10119 | 2016-02-17 00:00:00 | 2016 | 2 | 17 | t
10120 | 2016-02-18 00:00:00 | 2016 | 2 | 18 | t
I want the get the today_date of last 7 working date. Supporse today_date is 2016-02-18 and date of last 7 working dates as 2016-02-09.
You can use row_number() for this like this:
SELECT * FROM
(SELECT t.*,row_number() OVER(order by today_date desc) as rnk
FROM Calender t
WHERE today_date <= current_date
AND is_business_day = 't')
WHERE rnk = 7
This will give you the row of the 7th business day from todays date
I see that you tagged your question with Doctrine, ORM and Datetime. Were you after a QueryBuilder solution? Maybe this is closer to what you want:
$qb->select('c.today_date')
->from(Calendar::class, 'c')
->where("c.today_date <= :today")
->andWhere("c.is_business_day = 't'")
->setMaxResults(7)
->orderBy("c.today_date", "DESC")
->setParameter('today', new \DateTime('now'), \Doctrine\DBAL\Types\Type::DATETIME));

Summing columns in a row in all rows with Emacs org-mode

I'm using Emacs org-mode to track times worked on various tasks. The last column in the table is the weekly sum for each task:
|------+-----+-----+-----+-----+-----+-------|
| Task | Mon | Tue | Wed | Thu | Fri | Total |
|------+-----+-----+-----+-----+-----+-------|
| Foo | 2 | 3 | 4 | 5 | 6 | 20 |
| Bar | 2 | 3 | 4 | 5 | 7 | 21 |
#+TBLFM: #2$7=vsum($2..$6)::#3$7=vsum($2..$6)
Currently, I have to add a formula for each new row. Is there any way to customise the formula so that it calculates the sums regardless of how many rows there are?
Column formula did the trick as suggested by fniessen. Here's what I ended up with:
|------+-----+-----+-----+-----+-----+-------|
| Task | Mon | Tue | Wed | Thu | Fri | Total |
|------+-----+-----+-----+-----+-----+-------|
| Foo | 2 | 3 | 4 | 5 | 6 | 20 |
| Bar | 2 | 3 | 4 | 5 | 7 | 21 |
#+TBLFM: $7=vsum($2..$6)
More info in the Column formulas and field formulas section from the docs.
You really should take a closer look at the documentation, and read about "column formulas" (and, even, "row formulas"). A colum formula is $7=...' and is editable viaC-c ='.