Advanced SQL SUM COLUMN FROM A SAME TABLE - sql

I have this table...
+-----+--------+------+-----+-----+
|categ| nAME | quan |IDUNQ| ID|
+-----+--------+------+-----+-----+
| 1 | Z | 3 | 1 | 15 |
| 1 | A | 3 | 2 | 16 |
| 1 | B | 3 | 3 | 17 |
| 2 | Z | 2 | 4 | 15 |
| 2 | A | 2 | 5 | 16 |
| 3 | Z | 1 | 6 | 15 |
| 3 | B | 1 | 7 | 17 |
| 2 | Z | 1 | 8 | 15 |
| 2 | C | 4 | 8 | 15 |
| 1 | D | 1 | 8 | 15 |
+-----+--------+------+-----+-----+
I need to get the Z of category 1 + Z of category 2 - Z of category 3
For example, (3+3-1) = 5 ==> 3 of cat 1, 3 of cat 2, 1 of cat 3
The final result should be...
Z ==> 5
A ==> 5
B ==> 2
C ==> 4

Note: I'm assuming the data for "C" from your example was mistakenly omitted.
SELECT nAME, SUM(CASE categ WHEN 3 THEN 0-quan ELSE quan END) AS quan
FROM theTable
GROUP BY nAME
SQL Fiddle

SELECT name, SUM(quan) AS sum
FROM tableName
GROUP BY name, categ
This should work.

Related

How to assign duplicate increment in SQL?

While going through SQL columns, if we find text match "NEW" in Calc column, update the incrementing a count starting with 1 in Results column.
It should look like this on the output:
The following uses an id column to resolve the order issue. Replace that with your corresponding expression. This also addresses the requirement to start the display sequence with 1 and also show 0 for the 'NEW' rows.
The SQL (updated):
SELECT logs.*
, CASE WHEN text = 'NEW' THEN 0
ELSE
COALESCE(SUM(CASE WHEN text = 'NEW' THEN 1 END) OVER (PARTITION BY xrank ORDER BY id)+1, 1)
END AS display
FROM logs
ORDER BY id
The result:
+----+-------+------+---------+
| id | xrank | text | display |
+----+-------+------+---------+
| 1 | 1 | A | 1 |
| 2 | 1 | B | 1 |
| 3 | 1 | C | 1 |
| 4 | 1 | NEW | 0 |
| 5 | 1 | D | 2 |
| 6 | 1 | Q | 2 |
| 7 | 1 | B | 2 |
| 8 | 1 | NEW | 0 |
| 9 | 1 | D | 3 |
| 10 | 1 | Z | 3 |
| 11 | 2 | A | 1 |
| 12 | 2 | B | 1 |
| 13 | 2 | C | 1 |
| 14 | 2 | NEW | 0 |
| 15 | 2 | D | 2 |
| 16 | 2 | Q | 2 |
| 17 | 2 | B | 2 |
| 18 | 2 | NEW | 0 |
| 19 | 2 | D | 3 |
| 20 | 2 | Z | 3 |
+----+-------+------+---------+
You need a column that specifies the ordering for the table. With that, just use a cumulative sum:
select t.*,
1 + sum(case when Calc = 'NEW' then 1 else 0 end) over (partition by Rank_Id order by Seq) as display
from t;

Unpivoting in db2

I have the below table
+------+------+---+---+---+
| type | year | a | b | c |
+------+------+---+---+---+
| x | 2015 | 1 | 1 | 1 |
| x | 2015 | 2 | 2 | 2 |
| x | 2017 | 3 | 3 | 3 |
| y | 2016 | 1 | 1 | 1 |
| y | 2017 | 2 | 2 | 2 |
| z | 2015 | 1 | 1 | 1 |
| z | 2016 | 3 | 3 | 3 |
+------+------+---+---+---+
The expected result must be as follows
+------+------+---+---+---+
| type | year | x | y | z |
+------+------+---+---+---+
| a | 2015 | 3 | 0 | 1 |
| a | 2016 | 0 | 1 | 3 |
| a | 2017 | 3 | 2 | 0 |
| b | 2015 | 3 | 2 | 0 |
| b | 2016 | 0 | 1 | 3 |
| b | 2017 | 3 | 2 | 0 |
| c | 2015 | 3 | 0 | 1 |
| c | 2016 | 0 | 1 | 3 |
| c | 2017 | 3 | 2 | 0 |
+------+------+---+---+---+
So far, I could write the following query to obtain the result using simple group by in a pivot table manner, but i need to display the result in the unpivot manner as my expected result shown as above.
select type, year, sum(a) as a, sum(b) as b, sum(c) as c from table group by type,year;
The result of the above query is a valuable result for me but in a different format
+------+------+---+---+---+
| type | year | a | b | c |
+------+------+---+---+---+
| x | 2015 | 3 | 3 | 3 |
| x | 2017 | 3 | 3 | 3 |
| y | 2016 | 1 | 1 | 1 |
| y | 2017 | 2 | 2 | 2 |
| z | 2015 | 1 | 1 | 1 |
| z | 2016 | 3 | 3 | 3 |
+------+------+---+---+---+
You can unpivot using union all and then reaggregate:
select col_type, year,
sum(case when type = 'x' then val end) as x,
sum(case when type = 'y' then val end) as y,
sum(case when type = 'z' then val end) as z
from (select type, year, 'a' as col_type, a as val from t union all
select type, year, 'b' as col_type, b as val from t union all
select type, year, 'c' as col_type, c as val from t
) x
group by col_type, year;

Query with WITH clause and COUNT subquery

In the query below, I don't get the results i would expect. Any insights why? How could i reformulate such query to get the desired results?
Schema (SQLite v3.30)
WITH RECURSIVE
cnt(x,y) AS (VALUES(0,ABS(Random()%3)) UNION ALL SELECT x+1, ABS(Random()%3) FROM cnt WHERE x<10),
i_rnd as (SELECT r1.x, r1.y, (SELECT COUNT(*) FROM cnt as r2 WHERE r2.y<=r1.y) as idx FROM cnt as r1)
SELECT * FROM i_rnd ORDER BY y;
result:
| x | y | idx |
| --- | --- | --- |
| 1 | 0 | 3 |
| 5 | 0 | 6 |
| 8 | 0 | 5 |
| 9 | 0 | 4 |
| 10 | 0 | 2 |
| 3 | 1 | 4 |
| 0 | 2 | 11 |
| 2 | 2 | 11 |
| 4 | 2 | 11 |
| 6 | 2 | 11 |
| 7 | 2 | 11 |
expected result:
| x | y | idx |
| --- | --- | --- |
| 1 | 0 | 5 |
| 5 | 0 | 5 |
| 8 | 0 | 5 |
| 9 | 0 | 5 |
| 10 | 0 | 5 |
| 3 | 1 | 6 |
| 0 | 2 | 11 |
| 2 | 2 | 11 |
| 4 | 2 | 11 |
| 6 | 2 | 11 |
| 7 | 2 | 11 |
In other words, idx should indicate how many rows have y less or equal than the y of row considered.
I would just use:
select cnt.*,
count(*) over (order by y)
from cnt;
Here is a db<>fiddle.
The issue with your code is probably that the CTE is re-evaluated each time it is called, so the values are not consistent -- a problem with volatile functions in CTEs.

Multi update position based on ROW_NUMBER()

it might be a silly question but I am struggling with postgres update. I have following table:
id | tableX_id| position |
---+----------+---------+
1 | 10 | |
2 | 10 | |
3 | 10 | |
4 | 10 | |
5 | 10 | |
6 | 11 | |
7 | 11 | |
8 | 12 | |
I need to update position like this:
id | tableX_id| position |
---+----------+---------+
1 | 10 | 1 |
2 | 10 | 2 |
3 | 10 | 3 |
4 | 10 | 4 |
5 | 10 | 5 |
6 | 11 | 1 |
7 | 11 | 2 |
8 | 12 | 1 |
I have following update that doesnt work(update all position to 1):
UPDATE tableY y
SET position = subquery.pos
FROM (
SELECT ROW_NUMBER() OVER() as pos
FROM tableY y2
JOIN tableX x on x.id = y2.tableX_id
) as subquery
add where subquery.id = tableY.id, as below:
t=# update x set position = pos
from (select *,ROW_NUMBER() OVER(partition by x order by id) as pos FROM x) sub
where x.id = sub.id;
UPDATE 8
Time: 10.015 ms
t=# select * from x;
id | x | position
----+----+----------
1 | 10 | 1
2 | 10 | 2
3 | 10 | 3
4 | 10 | 4
5 | 10 | 5
6 | 11 | 1
7 | 11 | 2
8 | 12 | 1
(8 rows)

How to select if similar field count is the maximum in the table?

I want to select from a table if row counts of similar filed is maximum depends on other columns.
As example
| user_id | team_id | isOk |
| 1 | 1 | 1 |
| 2 | 1 | 1 |
| 3 | 1 | 1 |
| 4 | 1 | 1 |
| 5 | 2 | 1 |
| 6 | 2 | 1 |
| 7 | 2 | 1 |
| 8 | 3 | 1 |
| 9 | 3 | 1 |
| 10 | 3 | 1 |
| 11 | 3 | 0 |
So i want to select team 1 and 2 because they all have 1 value at isOk Column,
i tried to use this query
SELECT Team
FROM _Table1
WHERE isOk= 1
GROUP BY Team
HAVING COUNT(*) > 3
But still i have to define a row count which can be maximum or not.
Thanks in advance.
Is this what you are looking for?
select team
from _table1
group by team
having min(isOk) = 1;