SQL change the specific row - sql

In my table below, i want to change the placement of specific row.
For example,
ID Name Count
1 X 50
2 Y 30
3 other 25
4 Z 20
It is DESC ordered and i would like to see X,Y,Z orderly. Also, in total, 'other' should be counted. In other words, count should be 125.

You can use union all and add last row to the end.
Something like this:
select id, name,count from table where name<>other
union all
select 4 as id, "other"as name, 135 as count from table
order by 1
or if you want to sum it
select id, name,count from table where name<>other
union all
select 4 as id, 'other' as name, sum(count) as count from table
order by 1

You can put some logic in the order by clause:
select id, name, count
from table
order by case when id <> 3 then 1 else 2 end, id
This way, the first ordering criteria is "rows X, Y, Z first, then the other ones", then you order the groups the way you want, in your case either by id or by name will work.
You can find a working example here

TRY THIS :
SELECT ID,
Name,
CASE
WHEN Name = 'OTHER' THEN (SELECT SUM (COUNT) FROM YOUR_TABLE)
ELSE SUM (COUNT)
END
FROM YOUR_TABLE
GROUP BY Name
ORDER BY Name DESC

I think union all may be the simplest approach, but like this:
select id, name, count
from ((select id, name, count, 1 as ord
from t
where name in ('X', 'Y', 'Z')
) union all
(select 4, 'other', sum(count), 2 as ord
from t
)
) t
order by ord, name;

Related

BigQuery SQL: Sum of first N related items

I would like to know the sum of a value in the first n items in a related table. For example, I want to get the sum of a companies first 6 invoices (the invoices can be sorted by ID asc)
Current SQL:
SELECT invoices.company_id, SUM(invoices.amount)
FROM invoices
JOIN companies on invoices.company_id = companies.id
GROUP BY invoices.company_id
This seems simple but I can't wrap my head around it.
Consider also below approach
select company_id, (
select sum(amount)
from t.amounts amount
) as top_six_invoices_amount
from (
select invoices.company_id,
array_agg(invoices.amount order by invoices.invoice_id limit 6) amounts
from your_table invoices
group by invoices.company_id
) t
You can create order row numbers to the lines in a partition based on invoice id and filter to it, something like this:
with array_table as (
select 'a' field, * from unnest([3, 2, 1 ,4, 6, 3]) id
union all
select 'b' field, * from unnest([1, 2, 1, 7]) id
)
select field, sum(id) from (
select field, id, row_number() over (partition by a.field order by id desc) rownum
from array_table a
)
where rownum < 3
group by field
More examples for analytical examples here:
https://medium.com/#aliz_ai/analytic-functions-in-google-bigquery-part-1-basics-745d97958fe2
https://cloud.google.com/bigquery/docs/reference/standard-sql/analytic-function-concepts

SQL: Add number of unique values in a group

I have a table such as:
date
id
value
2020/4/4
1
a
2020/4/4
1
a
2020/4/4
1
b
2020/4/4
2
t
2020/4/4
2
u
2020/5/4
3
u
I want to find out how many IDs have more than one unique value at a particular date.
So this is what I should get for the table from above:
2020/4/4: 1 (=> only ID=1 has more than one unique value (a+b))
2020/4/5: 0
I tried to get it with:
SELECT date, SUM(CASE WHEN COUNT(DISTINCT value)>1 THEN 1 ELSE 0 END)
FROM table
GROUP BY date, id
But it did not work. How do I do it right?
Some databases will let you count "tuples", allowing this...
SELECT
date,
CASE WHEN COUNT(DISTINCT (id, value)) > COUNT(*) THEN 1 ELSE 0 END)
FROM
table
GROUP BY
date
Otherwise your style of approach works, but you need to aggregate twice using sub-queries.
SELECT date, MAX(has_duplicate_values)
FROM
(
SELECT date, id, CASE WHEN COUNT(DISTINCT value) > COUNT(*) THEN 1 ELSE 0 END has_duplicate_values
FROM table
GROUP BY date, id
)
AS date_id_aggregate
GROUP BY date
modify your request as following:
SELECT date, CASE WHEN COUNT(DISTINCT value)>1 THEN 1 ELSE 0 END FROM `table` GROUP BY date
I want to find out how many IDs have more than one unique value at a particular date.
You can aggregate twice:
SELECT date,
SUM(CASE WHEN num > num_distinct_values THEN 1 ELSE 0 END) as num_ids_with_duplicates
FROM (SELECT date, id,
COUNT(DISTINCT value) as num_distinct_values,
COUNT(*) as num
FROM table
GROUP BY date, id
) di
GROUP BY date;

select two grouped by columns but only select row with the highest COUNT()

I have a table that consists of three columns - UPC, ATTRIBUTE, STORE_NUM. I have 10 stores and 2 UPCs at each with different ATTRIBUTEs.
Every store either has either attribute X or Y. I group by UPC and ATTRIBUTE and get the count of stores.
SELECT [UPC], [ATTRIBUTE], COUNT([STORE_NUM]) AS [COUNT]
FROM TABLEA
GROUP BY [UPC], [ATTRIBUTE]
Yields this:
UPC ATTRIBUTE COUNT
1 X 8
1 Y 2
2 X 1
2 Y 9
And I want to select UPC and ATTRIBUTE with the highest count. My desired output would be this:
UPC ATTRIBUTE
1 X
2 Y
I can't figure out how to reach this desired outcome.
You can use window functions with aggregation:
SELECT *
FROM (SELECT [UPC], [ATTRIBUTE], COUNT(*) AS [COUNT],
ROW_NUMBER() OVER (PARTITION BY UPC ORDER BY COUNT(*) DESC) as seqnum
FROM TABLEA
GROUP BY [UPC], [ATTRIBUTE]
) x
WHERE seqnum = 1;
Use RANK() if you want duplicates in the event of ties.
Use row_number and a subquery:
SELECT UPC, ATTRIBUTE
FROM (
SELECT UPC, ATTRIBUTE, ROW_NUMBER() OVER (PARTITION BY UPC ORDER BY a_count DESC) as rn
FROM ( SELECT [UPC],[ATTRIBUTE],COUNT([STORE_NUM]) AS [a_COUNT]
FROM TABLEA
GROUP BY [UPC],[ATTRIBUTE]
) t
) q
WHERE q.rn = 1

SUM of grouped COUNT in SQL Query

I have a table with 2 fields:
ID Name
-- -------
1 Alpha
2 Beta
3 Beta
4 Beta
5 Charlie
6 Charlie
I want to group them by name, with 'count', and a row 'SUM'
Name Count
------- -----
Alpha 1
Beta 3
Charlie 2
SUM 6
How would I write a query to add SUM row below the table?
SELECT name, COUNT(name) AS count
FROM table
GROUP BY name
UNION ALL
SELECT 'SUM' name, COUNT(name)
FROM table
OUTPUT:
name count
-------------------------------------------------- -----------
alpha 1
beta 3
Charlie 2
SUM 6
SELECT name, COUNT(name) AS count, SUM(COUNT(name)) OVER() AS total_count
FROM Table GROUP BY name
Without specifying which rdbms you are using
Have a look at this demo
SQL Fiddle DEMO
SELECT Name, COUNT(1) as Cnt
FROM Table1
GROUP BY Name
UNION ALL
SELECT 'SUM' Name, COUNT(1)
FROM Table1
That said, I would recomend that the total be added by your presentation layer, and not by the database.
This is a bit more of a SQL SERVER Version using Summarizing Data Using ROLLUP
SQL Fiddle DEMO
SELECT CASE WHEN (GROUPING(NAME) = 1) THEN 'SUM'
ELSE ISNULL(NAME, 'UNKNOWN')
END Name,
COUNT(1) as Cnt
FROM Table1
GROUP BY NAME
WITH ROLLUP
Try this:
SELECT ISNULL(Name,'SUM'), count(*) as Count
FROM table_name
Group By Name
WITH ROLLUP
all of the solution here are great but not necessarily can be implemented for old mysql servers (at least at my case). so you can use sub-queries (i think it is less complicated).
select sum(t1.cnt) from
(SELECT column, COUNT(column) as cnt
FROM
table
GROUP BY
column
HAVING
COUNT(column) > 1) as t1 ;
Please run as below :
Select sum(count)
from (select Name,
count(Name) as Count
from YourTable
group by Name); -- 6
The way I interpreted this question is needing the subtotal value of each group of answers. Subtotaling turns out to be very easy, using PARTITION:
SUM(COUNT(0)) OVER (PARTITION BY [Grouping]) AS [MY_TOTAL]
This is what my full SQL call looks like:
SELECT MAX(GroupName) [name], MAX(AUX2)[type],
COUNT(0) [count], SUM(COUNT(0)) OVER(PARTITION BY GroupId) AS [total]
FROM [MyView]
WHERE Active=1 AND Type='APP' AND Completed=1
AND [Date] BETWEEN '01/01/2014' AND GETDATE()
AND Id = '5b9xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' AND GroupId IS NOT NULL
GROUP BY AUX2, GroupId
The data returned from this looks like:
name type count total
Training Group 2 Cancelation 1 52
Training Group 2 Completed 41 52
Training Group 2 No Show 6 52
Training Group 2 Rescheduled 4 52
Training Group 3 NULL 4 10535
Training Group 3 Cancelation 857 10535
Training Group 3 Completed 7923 10535
Training Group 3 No Show 292 10535
Training Group 3 Rescheduled 1459 10535
Training Group 4 Cancelation 2 27
Training Group 4 Completed 24 27
Training Group 4 Rescheduled 1 27
You can use union to joining rows.
select Name, count(*) as Count from yourTable group by Name
union all
select "SUM" as Name, count(*) as Count from yourTable
For Sql server you can try this one.
SELECT ISNULL([NAME],'SUM'),Count([NAME]) AS COUNT
FROM TABLENAME
GROUP BY [NAME] WITH CUBE
with cttmp
as
(
select Col_Name, count(*) as ctn from tab_name group by Col_Name having count(Col_Name)>1
)
select sum(ctn) from c
You can use ROLLUP
select nvl(name, 'SUM'), count(*)
from table
group by rollup(name)
Use it as
select Name, count(Name) as Count from YourTable
group by Name
union
Select 'SUM' , COUNT(Name) from YourTable
I am using SQL server and the following should work for you:
select cast(name as varchar(16)) as 'Name', count(name) as 'Count'
from Table1
group by Name
union all
select 'Sum:', count(name)
from Table1
I required having count(*) > 1 also. So, I wrote my own query after referring some the above queries
SYNTAX:
select sum(count) from (select count(`table_name`.`id`) as `count` from `table_name` where {some condition} group by {some_column} having count(`table_name`.`id`) > 1) as `tmp`;
Example:
select sum(count) from (select count(`table_name`.`id`) as `count` from `table_name` where `table_name`.`name` IS NOT NULL and `table_name`.`name` != '' group by `table_name`.`name` having count(`table_name`.`id`) > 1) as `tmp`;
You can try group by on name and count the ids in that group.
SELECT name, count(id) as COUNT FROM table group by name
After the query, run below to get the total row count
select ##ROWCOUNT
select sum(s) from
(select count(Col_name) as s from Tab_name group by Col_name having count(*)>1)c

Getting rows with duplicate column values

I tried this with solutions avaialble online, but none worked for me.
Table :
Id rank
1 100
1 100
2 75
2 45
3 50
3 50
I want Ids 1 and 3 returned, beacuse they have duplicates.
I tried something like
select * from A where rank in (
select rank from A group by rank having count(rank) > 1
This also returned ids without any duplicates. Please help.
Try this:
select id from table
group by id, rank
having count(*) > 1
select id, rank
from
(
select id, rank, count(*) cnt
from rank_tab
group by id, rank
having count(*) > 1
) t
This general idea should work:
SELECT id
FROM your_table
GROUP BY id
HAVING COUNT(*) > 1 AND COUNT(DISTINCT rank) = 1
In plain English: get every id that exists in multiple rows, but all these rows have the same value in rank.
If you want ids that have some duplicated ranks (but not necessarily all), something like this should work:
SELECT id
FROM your_table
GROUP BY id
HAVING COUNT(*) > COUNT(DISTINCT rank)