Group BY Statement error to get unique records - sql

I am new to SQL Server, used to work with MYSQL and trying to get the records from a table using Group By.
The table structure is given below:
SELECT S1.ID,S1.Template_ID,S1.Assigned_By,S1.Assignees,S1.Active FROM "Schedule" AS S1;
Output:
ID Template_ID Assigned_By Assignees Active
2 25 1 3 1
3 25 5 6 1
6 26 5 6 1
I need to get the values of all columns using the Group By statement below
SELECT Template_ID FROM "Schedule" WHERE "Assignees" IN(6, 3) GROUP BY "Template_ID";
Output:
Template_ID
25
26
I tried the following code to fetch the table using Group By, but it's fetching all the rows.
SELECT S1.ID,S1.Template_ID,S1.Assigned_By,S1.Assignees,S1.Active FROM "Schedule" AS S1 INNER JOIN(SELECT Template_ID FROM "Schedule" WHERE "Assignees" IN(6, 3) GROUP BY "Template_ID") AS S2 ON S2.Template_ID=S1.Template_ID
My Output Should be like,
ID Template_ID Assigned_By Assignees Active
2 25 1 3 1
6 26 5 6 1
I was wondering whether I can get ID of the column as well? I use the ID for editing the records in the web.

The query doesn't work as expected in MySQL either, except by accident.
Nonaggregated columns in MySQL aren't part of the SQL standard and not even allowed in MySQL 5.7 and later unless the default value of the ONLY_FULL_GROUP_BY mode is changed.
In earlier versions the result is non-deterministic.
The server is free to choose any value from each group, so unless they are the same, the values chosen are nondeterministic. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause.
This means there's was no way to know what rows will be returned this query :
SELECT S1.ID,S1.Template_ID,S1.Assigned_By,S1.Assignees,S1.Active
FROM "Schedule" AS S1
GROUP BY Template_ID;
To get deterministic results you'd need a way to rank rows with the ranking functions introduced in MySQL 8, like ROW_NUMBER(). These are already available in SQL Server since SQL Server 2012 at least. The syntax is the same for both databases :
WITH ranked as AS
(
SELECT
ID,Template_ID,Assigned_By,Assignees Active,
ROW_NUMBER(PARTITION BY Template_ID Order BY ID)
FROM Scheduled
WHERE Assignees IN(6, 3)
)
SELECT ID,Template_ID,Assigned_By,Assignees Active
FROM ranked
Where RN=1
PARTITION BY Template_ID splits the result rows based on their Template_ID value into separate partitions. Within that partition, the rows are ordered based on the ORDER BY clause. Finally, ROW_NUMBER calculates a row number for each ordered partition row.

Related

Get the latest entry of each duplicate on Postgres

I am using Postgres v12, and I have a table with duplicated rows. I need to retrieve only the last entry for each duplicate, ignoring entries which have no duplicate.
This table has the following columns:
id (unique)
request_id (where to find the duplicates)
created_at (where to see which entry is the latest)
id
request_id
created_at
1
a
2020.06.06
2
a
2020.05.05
3
b
2020.04.04
4
b
2020.03.03
5
c
2020.04.04
6
c
2020.03.03
7
d
2020.03.03
The query should retrieve rows with id 1,3,5 , since they are the latest entry (created_at) of each duplicate. ID 7 has no duplicate, so it is ignored.
I have tried with the solution proposed here: https://www.geeksengine.com/article/get-single-record-from-duplicates.html but due to be using Postgres v12, those queries do not work, I get the error "column must appear in the group by clause" which is another problem cited here: must appear in the GROUP BY clause or be used in an aggregate function
I have been searching for a solution for days to this problem, but I am not an SQL expert. I would appreciate any help very much.
here is one way using window functions :
select * from (
select *
, row_number() over (partition by request_id order by created_at desc) as rn
, count() over (partition by request_id) cn
from tablename
) t where cn > 1 and rn = 1

Count duplicates (by assigning numbers) without grouping in SQL

I have data in Microsoft SQL Server:
Name
-----
A
A
B
D
R
A
B
Want to add a column that will count the entries by assigning ordered numbers like this:
Name Count
--------------
A 1
A 2
B 1
D 1
R 1
A 3
B 2
Your table seems to be lacking a column which would provide an ordering for the counts you are expecting. Since each entry is equivalent to the other, we can just order by Name and use ROW_NUMBER:
SELECT
Name,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Name) Count
FROM yourTable;
I also don't see any obvious ordering your expected result set. You would need a column(s) in order to impose an ordering there, too.

Sql to get unique rows

I have a table as below.
OId CustId CustSeq
1 A 10
1 A 20
2 A 10
2 A 20
I'm trying to extract unique records as below.
OId CustId CustSeq (Different OIds with different CustSeqs)
1 A 10
2 A 20
May I know how I could come out the query to extract like above?
Just use DISTINCT. That's what it was desgined for although group by will work.
http://www.techonthenet.com/oracle/distinct.php
SELECT DISTINCT OID, CUSTID, CUSTSEQ
FROM TABLE_NAME
Use DISTINCT, and also use Group By for the 2 columns CustId & CustSeq
Check here for example Is it possible to GROUP BY multiple columns using MySQL?

Updating tables from generate_series(int, int) function Postgres 9.0

I have a table with data in it I want to keep, but I have to add a new column of integers for ordering purposes. Now this ordering will be different depending on the clientID as each different client wants different ordering. So in my example there are 3 different clients, the first client has 10 rows of data the second has 15, and the third has 87. So basically I'm looking for a query that will let me update the ordering column in a way that will allow me to do a select on the table that would give results like this.
Select ordering from table Where clientID = 1
-----------
Ordering
1
2
3
4
5
6
7
8
9
10
Now the query I'm currently using to do this is
UPDATE data SET ordering = generate_series
FROM (SELECT * FROM generate_series(1,87)) as k <
where clientid = '3'
This will update all the correct rows but only with the first value, so all the values in ordering would be 1. I feel like I'm missing something here or this just doesn't work in postgres as it does in other SQL languages. Any solution here will help I would also like to know why my update would not work as I expected in postgres. Also I cannot change versions of postgres based on the environment I work in.
I don't see why you would need generate_series(). A window function that numbers all rows for each client should do:
update data
set ordering = t.rn
from (select pk_column,
row_number() over (partition by clientid order by pk_column) as rn
from data
) t
where t.pk_column = data.pk_column;
pk_column is the primary key column of the table data

SQL Server Sum multiple rows into one - no temp table

I would like to see a most concise way to do what is outlined in this SO question: Sum values from multiple rows into one row
that is, combine multiple rows while summing a column.
But how to then delete the duplicates. In other words I have data like this:
Person Value
--------------
1 10
1 20
2 15
And I want to sum the values for any duplicates (on the Person col) into a single row and get rid of the other duplicates on the Person value. So my output would be:
Person Value
-------------
1 30
2 15
And I would like to do this without using a temp table. I think that I'll need to use OVER PARTITION BY but just not sure. Just trying to challenge myself in not doing it the temp table way. Working with SQL Server 2008 R2
Simply put, give me a concise stmt getting from my input to my output in the same table. So if my table name is People if I do a select * from People on it before the operation that I am asking in this question I get the first set above and then when I do a select * from People after the operation, I get the second set of data above.
Not sure why not using Temp table but here's one way to avoid it (tho imho this is an overkill):
UPDATE MyTable SET VALUE = (SELECT SUM(Value) FROM MyTable MT WHERE MT.Person = MyTable.Person);
WITH DUP_TABLE AS
(SELECT ROW_NUMBER()
OVER (PARTITION BY Person ORDER BY Person) As ROW_NO
FROM MyTable)
DELETE FROM DUP_TABLE WHERE ROW_NO > 1;
First query updates every duplicate person to the summary value. Second query removes duplicate persons.
Demo: http://sqlfiddle.com/#!3/db7aa/11
All you're asking for is a simple SUM() aggregate function and a GROUP BY
SELECT Person, SUM(Value)
FROM myTable
GROUP BY Person
The SUM() by itself would sum up the values in a column, but when you add a secondary column and GROUP BY it, SQL will show distinct values from the secondary column and perform the aggregate function by those distinct categories.