Query to display unique comments based on certain conditions - sql

TABLE DEFINITION
ColumnName Comments
CustomerID INT
SequenceNo INT
Comments VARCHAR(MAX)
CUSTOMER TABLE
CustomerID SequenceNo Comments
1 1 ABC D
1 2 CDE
1 3 ABC
1 4 ABC D
1 5 CDE
1 6 abc
2 7 ABC DEF
2 8
2 9 ABC DEF
2 10 DEF
2 11 XYZ 123
2 12 ABC
3 13 PQ RST
OUTPUT
CustomerID SequenceNo Comments
1 3 ABC
1 4 ABC D
1 5 CDE
1 6 abc
2 8
2 9 ABC DEF
2 10 DEF
2 11 XYZ 123
2 12 ABC
3 13 PQ RST
Records should be filtered by
1. Display only Unique Comments from Customer Table for all the customers,
2. If Comments are same then display the row which has maximum SequenceNo

This assumes you are using a case sensitive collation
SELECT CustomerID,
MAX(SequenceNo) AS SequenceNo,
Comments
FROM yourTable
GROUP BY CustomerID,Comments
ORDER BY CustomerID,MAX(SequenceNo)
If you are not using a case sensitive collation, then try this:
SELECT CustomerID,
MAX(SequenceNo) AS SequenceNo,
Comments COLLATE SQL_Latin1_General_CP1_CS_AS
FROM yourTable
GROUP BY CustomerID,Comments COLLATE SQL_Latin1_General_CP1_CS_AS
ORDER BY CustomerID,MAX(SequenceNo)

You can use window functions for this:
select c.*
from (select c.*,
row_number() over (partition by CustomerId, Comments
order by SequenceNo desc) as seqnum
from comments c
) c
where seqnum = 1;

Related

Select from same column but multiples values and number of records with one specific value

ID Customer Status
1 ABC 1
2 ABC 2
3 ABC 3
4 ABC 1
5 PQR 1
6 PQR 2
7 PQR 3
8 XYZ 1
9 XYZ 3
I want to select customer who has both values "status=1" and "Status=2' and also total number of entry of same customer with Status=1.
So the result will be,
Customer totalEntryStatus1
ABC 2
PQR 1
How can I do this.
Thankyou !
select Customer, count(case when status = 1 then 1 end) totalEntryStatus1
from table
where Status in (1,2)
group by Customer
having count(distinct Status) = 2

How to add auto increment id according to a group in VFP 9 and SQL Server

Here is the format of the table:
No group name
1 abc a
1 xyz c
1 xyz d
Now i want it to be like,
No group name
1 abc a
2 abc b
3 abc f
1 xyz c
2 xyz h
1 xyz d
"No" should auto increment according to "group"
Thank you
You can use windowing function:
Select group,
name,
row_number() over (partition by group order by name) as No
from table

How to select x or y members of each group based on a condition

Using SQL Server 2012. I have thousands of groups in a table and I need to be able to select either everything but the top member or everything but the top two members of each group based on a quantity each group member has. The groups are not explicitly called out, but I can assign group numbers using a window function. To illustrate my question, here's some sample data:
Group Attribute ProductClass Product Quantity
1 abc xaxa xx1000 16
1 abc xaxa xx1019 15
1 def xaxa xx1938 13
1 abc xaxa xx1021 10
2 def xaxa xx1031 18
2 def xaxa xx3013 17
2 abc xaxa xx4810 14
3 abc xaxb xx0110 18
3 def xaxb xx3810 15
3 def xaxb xx2010 11
3 def xaxb xx1002 8
3 def xaxb xx1040 2
3 abc xaxb xx0023 2
4 def xaxb xx4918 14
4 abc xaxb xx1414 11
4 abc xaxb xx4182 11
4 def xaxb xx1004 2
Here's the desired output:
Group Attribute ProductClass Product Quantity
1 def xaxa xx1938 13
1 abc xaxa xx1021 10
2 def xaxa xx3013 17
2 abc xaxa xx4810 14
3 def xaxb xx2010 11
3 def xaxb xx1002 8
3 def xaxb xx1040 2
3 abc xaxb xx0023 2
4 abc xaxb xx1414 11
4 abc xaxb xx4182 11
4 def xaxb xx1004 2
There are only two attributes in the "attribute" column. Note that for "abc" I want the top two products by quantity, while for "def" I just want the top product by quantity.
I've created code that can select for everything but the top row for each group, and code that can assign a group name. I just can't get beyond this part:
SELECT
p.Group,
p.Attribute,
p.ProductClass,
p.Product,
p.Quantity
FROM (SELECT *,
ROW_NUMBER() OVER(PARTITION BY ProductClass, Product ORDER BY Quantity DESC) AS RowNum,
DENSE_RANK() OVER(ORDER BY ProductClass, Product) AS Group
FROM table
WHERE brand = 'brand') AS p
WHERE RowNum > 1;
Note that ProductClass and Product together create the unique groupings.
Thanks so much in advance!
Rank() instead of row_number() almost gets you there. The problem is that the rows are tied for 2nd place, not 3rd.
SELECT p.Group, p.Attribute, p.ProductClass, p.Product, p.Quantity
FROM (SELECT t.*,
RANK() OVER (PARTITION BY ProductClass, Product ORDER BY Quantity DESC) AS RowNum,
COUNT(*) OVER (PARTITION BY ProducctClass, Product, Count) as cnt,
DENSE_RANK() OVER (ORDER BY ProductClass, Product) AS Group
FROM table t
WHERE brand = 'brand'
) AS p
WHERE RowNum = 1 OR (RowNum = 2 AND cnt = 1);
This gets the top value for each group. In addition, it will get the second value if it is not duplicated and if it does not match the top value. That appears to be the logic you want.

SQL Server: SELECT value with multiple criteria

Looking for a SQL solution to the following problem
Return USER and NUMBER combination WHERE PRIORITY = MIN(PRIORITY) [NULL is equivalent to MAX(PRIORITY + 1)] ... in the case of ties in PRIORITY, break using lowest LINEITEM
FIELDS:
USER,
LINEITEM,
NUMBER,
PRIORITY
VALUES: ('X' signifies desired combination)
USER LINEITEM NUMBER PRIORITY
-------------------------------------
1 1 12345 NULL
1 2 23456 2
1 3 34567 1 X
2 1 9876 3
2 2 98765 1 X
2 3 12345 2
2 4 23456 1
3 1 23456 NULL X
3 2 12345 NULL
4 1 34567 NULL
4 2 45678 NULL
4 3 12345 1 X
4 4 12345 2
4 5 23456 1
Thanks in advance.
In response to PM 77-1,
My current method:
SELECT table1.user,table1.number
FROM table1
JOIN (
SELECT user,
CAST(MIN((COALESCE(priority,999) *
(10 ^ (5 - LEN(COALESCE(CAST(priority AS VARCHAR),'999'))))) +
lineitem) AS VARCHAR) AS selector
FROM table1 GROUP BY user
) AS table2
ON table1.user = table2.user
AND table1.lineitem = CAST(RIGHT(table2.selector, 1) AS int)
ORDER BY table1.user;
Use ROW_NUMBER:
SQL Fiddle
;WITH Cte AS(
SELECT *,
ROW_NUMBER() OVER(
PARTITION BY [User]
ORDER BY
CASE WHEN Priority IS NULL THEN 1 ELSE 0 END,
Priority,
LineItem
) AS rn
FROM tbl
)
SELECT
[User], LineItem, Number, Priority
FROM Cte
WHERE rn = 1

Updating column based on another column's value

How do i update table structured like this:
id[pkey] | parent_id | position
1 1
2 1
3 1
4 1
5 1
6 2
7 2
8 2
9 2
10 3
11 3
12 3
...and so on
to achieve this result:
id[pkey] | parent_id | position
1 1 1
2 1 2
3 1 3
4 1 4
5 1 5
6 2 1
7 2 2
8 2 3
9 2 4
10 3 1
11 3 2
12 3 3
...and so on
I was thinking about somehow mixing
SELECT DISTINCT parent_id FROM cats AS t;
with
CREATE SEQUENCE dpos;
UPDATE cats t1 SET position = nextval('dpos') WHERE t.parent_id = t1.parent_id;
DROP SEQUENCE dpos;
although im not really experienced with postgres, and not sure how to use some kind of FOREACH. I appreciate any help
You can get the incremental number using row_number(). The question is how to assign it to a particular row. Here is one method using a join:
update cats
set position = c2.newpos
from (select c2.*, c2.ctid as c_ctid,
row_number() over (partition by c2.parent_id order by NULL) as seqnum
from cats c2
) c2
where cats.parent_id = c2.parent_id and cats.ctid = c2.c_ctid;
Use row_number function
select parent_id,
row_number() over (partition by parent_id order by parent_id) as position_id from table
Try this:
UPDATE table_name set table_name.dataID = v_table_name.rn
FROM
(
SELECT row_number() over (partition by your_primaryKey order by your_primaryKey) AS rn, id
FROM table_name
) AS v_table_name
WHERE v_table_name.your_primaryKey = v_table_name.your_primaryKey;