How to SQL distinct with ORDER BY [duplicate] - sql

This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed last year.
How do i bring the rows distinctly by OrderID and those who has ProductID 1. if there is no 1 then bring 2
I've tried:
Select DISTINCT OrderDetailID,OrderID,ProductID,Quantity from Products
ORDER BY OrderID,ProductID
OrderDetailID
OrderID
ProductID
Quantity
1
10248
1
12
2
10248
2
10
3
10249
1
5
4
10250
1
9
5
10250
2
40
6
10251
2
10
7
10252
1
35
8
10252
2
15
9
10253
2
6
10
10254
2
15
Output should be like this:
OrderDetailID
OrderID
ProductID
Quantity
1
10248
1
12
3
10249
1
5
4
10250
1
9
6
10251
2
10
7
10252
1
35
9
10253
2
6
10
10254
2
15

Use row_number window function
select OrderDetailID,OrderID,ProductID,Quantity
from
select *,row_number()over(partition by OrderID order by OrderDetailID) as seq
from ) t
where seq = 1

You can use row_number to asign ordering to each group of ProductId
with o as (
select *,
Row_Number() over(partition by orderid order by productid) rn
from t
)
select OrderDetailID, OrderID, ProductID, Quantity
from o
where rn=1

Related

T-SQL How to configure Group by so that specific values would be correctly shown

My current T-SQL query provides the following results:
Query:
WITH CTE AS
(
SELECT SubscriberID, sum(valueMB) as ValuesMB
FROM dbo.InternetNetwork
GROUP BY SubscriberID
),
CTE2 AS (
SELECT ab.planID, a.SubscriberID, MAX(ValuesMB) as MaximumValue
FROM CTE AS a
left join
Subscriber as ab on a.SubscriberID= ab.SubscriberID
GROUP BY ab.planID, a.SubscriberID
)
select *
FROM CTE2 as b
ORDER BY b.MaximumValue desc
Output:
planID | SubscriberID | MaxValue
19 1555 97536.00
18 3528 97478.00
2 4029 93413.00
Query #2:
WITH CTE AS
(
SELECT SubscriberID, sum(valueMB) as ValuesMB
FROM dbo.InternetNetwork
GROUP BY SubscriberID
),
CTE2 AS(
SELECT ab.planID, MAX(ValuesMB) as MaximumValue
FROM CTE AS a
left join
Subscriber as ab on a.SubscriberID= ab.SubscriberID
GROUP BY ab.planID
)
SELECT pl.OperatorID, MAX(b.MaximumValue) as Super
FROM CTE2 as b
left join
Plan as pl on b.planID= pl.planID
GROUP BY pl.operatorID
ORDER BY pl.operatorID
Output #2:
OperatorID | Value
1 93413.00
2 86017.00
3 97536.00
I would like to also include a subscriberID, but I'm unable to figure out a way to do so, as the only way to do it, is including in the last SELECT and adding to GROUP BY, which when done, makes a mess of a result which is not accurate.
My desired output:
OperatorID | Value | SubscriberID
1 93413.00 4029
2 86017.00 164
3 97536.00 1544
internet network data:
SubscriberID ValuesMB
1 28
1 27
2 27
2 27
2 27
3 29
3 28
3 27
3 27
4 27
4 27
4 29
Subscriber Data:
SubscriberID PersonID PlanID
1 1 3
2 2 10
3 2 6
4 3 14
5 3 1
6 4 18
7 5 5
8 5 1
9 5 9
10 5 16
11 6 13
12 6 13
13 6 20
14 6 16
15 7 4
Plan data
PlanID OperatorID
1 1
2 1
3 2
4 2
5 2
6 2
7 2
8 2
9 2
10 2
11 2
12 3
13 3
14 3
15 3
16 3
17 3
18 3
19 3
20 3
The tables are somewhat like this related InternetNetwork-> Subscriber -> Plan. InternetNetwork contains how much each Subscribed has used. Each Subscriber has Plan associated with him. Each Plan contains a different Operator, there are only three. I wish to list all three operators, the data transferred by the subscriber of the plan that has the operator and Subscriber ID.
Window functions allow you to have fields in your select along with aggregate functions. You can do something like this
;WITH CTE AS
(
SELECT I.SubscriberID,
S.PlanID,
SUM(ValuesMB) OVER(PARTITION BY i.SubscriberID)as ValuesMB
FROM dbo.InternetNetwork I
JOIN Subscriber S
ON I.SubscriberID = S.SubscriberID
),
CTE2 AS
(
SELECT p.operatorID,
a.SubscriberID,
a.ValuesMB,
ROW_NUMBER() OVER(PARTITION BY p.operatorID ORDER BY a.ValuesMB DESC) as rn
FROM CTE a
join [Plan] P
on a.planID = P.planID
)
SELECT operatorID,
ValuesMB,
SubscriberID
FROM CTE2
where rn = 1

SQL select latest values in a many-to-many table

How can I select latest records in a a table with many-to-many relationship. The store_id,product_id is not a composite group key so they repeat many times.
id store_id product_id
1 1 1
2 2 1
3 1 1
4 3 1
5 2 1
6 3 1
The result should be like this:
id store_id product_id
3 1 1
5 2 1
6 3 1
For the sake of simplicity I only added 1 product but in the real case there are many products. So the result should be something like :
For each store_id show the latest added products_id.
e.g.
id store_id product_id
11 1 1
20 1 2
40 1 3
41 1 4
53 2 1
61 2 2
62 2 3
63 2 4
70 3 1
71 3 2
72 3 3
73 3 4
I don't see what this has to do with a pivot table. This seems like a basic aggregation:
select max(id) as id, store_id, product_id
from t
group by store_id, product_id
order by store_id, max(id);

How to get 2 most recent values in postgreSQL in one row?

I have this table of items in order:
orderitemid orderid itemid quantity price createdate
1 1 12 5 15.5 2016-12-04 11:35:02.06629
2 1 17 5 13.2 2016-12-04 11:32:02.06629
3 2 12 2 12.5 2016-12-05 11:35:02.06629
4 2 17 1 12.6 2016-12-05 11:35:02.06629
5 2 18 15 14.5 2016-12-04 11:35:02.06629
6 3 12 45 3 2015-12-04 11:35:02.06629
I have a query which gives the most recent order of each item so:
select distinct on (itemid) *
from orderitems
order by itemid,createdate
this gives:
orderitemid orderid itemid quantity price createdate
3 2 12 2 12.5 2016-12-05 11:35:02.06629
4 2 17 1 12.6 2016-12-05 11:35:02.06629
5 1 18 15 14.5 2016-12-04 11:35:02.06629
Now what I want is to get in the same row per item information about the previous order of the item. Basically to compare the most recent order of item with the 2nd most recent order of item
This is what I want:
orderitemid itemid quantity price 2ndquantity 2ndprice 2ndorderitemid
3 12 2 12.5 5 15.5 1
4 17 1 12.6 1 13.2 2
5 18 15 14.5
How can I modify my query to do that?
with ranked as (
select orderitemid, orderid, itemid, quantity, price, createdate,
row_number() over (partition by itemid order by createdate desc) as rn
from orderitems
)
select r1.*, r2.quantity as "2ndquantity", r2.price as "2ndprice",
r2.orderitemid as "2ndorderitemid"
from ranked r1
left join ranked r2 on r1.itemid = r2.itemid and r2.rn = 2
where r1.rn = 1;
The CTE calculates the 1st and 2nd items and the final select then brings them together with a join. Note that you need a left join as there might not be a 2nd row and in that case that item would not show up at all.
Online example: http://rextester.com/SDBZ21144
Hmmm you want to compare all orderitem rows against the next most recent price?
WITH comparison_rank AS (
SELECT orderitemid, itemid, price, quantity
rank() over (partition by itemid order by createddate)
FROM orderitems
)
SELECT o.orderitemid, o.itemid, o.price, o.quantity, o.price, o.createddate,
p.price as prevprice, p.quantity as prevqty
FROM orderitems o JOIN comparison_rank c ON o.orderitemid = c.orderitemid
LEFT JOIN comparison_rank p ON c.rank = p.rank + 1 AND c.itemid = p.itemid;
This will not perform so well over a large data set however. To improve performance I think you need to improve your data model to improve performance.

Queries to fetch items based on top Ranks

I have a table which rank the items which i have.
I need a queries which will pick up only the top 2 ranks for a given item, the rank may not be in sequential order.
I need to fetch the item with least two ranks, there will same rank for two items as well.
Here is the snap shot of my table.
Item Id Supp Id Rank
1 2 2
1 1 7
1 7 5
1 9 11
2 67 4
2 9 14
2 10 14
2 34 4
2 25 3
2 60 3
2 79 5
my requirement is if I enter 2 i should get the result as below
Item Id Supp_id Rank
2 25 3
2 60 3
2 67 4
2 34 4
I am using oracle 10g version.
As one of the approaches it can be done as follows. Here we are using dense_rank() over() analytic function to assign a rank for a row in a ordered by rank group of rows .
select t.item_id
, t.supp_id
, t.rank
from (select item_id
, supp_id
, rank
, dense_rank() over(partition by item_id
order by rank) as rn
from t1
where item_id = 2
) t
where t.rn <= 2
Result:
ITEM_ID SUPP_ID RANK
---------- ---------- ----------
2 25 3
2 60 3
2 67 4
2 34 4
SQLFiddle Demo

How can I find duplicate orders per customer?

How can I query my SQL database and find all the duplicate orders where a customer ordered something more than once?
Not a super clear question, but I get the gist of it. I don't know what your database looks like, but your query would look something like this:
SELECT customer_id, count(*) FROM orders
GROUP BY customer_id
HAVING count(*) > 1
SELECT customerId, productId, count(productId)
FROM CustomerOrders
GROUP BY customerId
HAVING count(productId) > 1
A platform, version would help. So would a sample table. So here is a sample orders table:
SQL> select * from orders;
CUST_ID ORDER_ID ORDER_DAT
---------- ---------- ---------
1 1 25-FEB-09
1 2 24-FEB-09
1 3 23-FEB-09
2 4 24-FEB-09
2 5 23-FEB-09
2 6 22-FEB-09
3 7 23-FEB-09
9 8 22-FEB-09
9 9 21-FEB-09
4 10 22-FEB-09
4 11 21-FEB-09
4 12 20-FEB-09
5 13 21-FEB-09
5 14 20-FEB-09
5 15 19-FEB-09
6 16 20-FEB-09
11 17 19-FEB-09
10 18 18-FEB-09
7 19 19-FEB-09
7 20 18-FEB-09
7 21 17-FEB-09
8 22 18-FEB-09
8 23 17-FEB-09
8 24 16-FEB-09
24 rows selected.
The following select works on this table for a simple output:
1* select cust_id, count(*) from orders group by cust_id having count(*) > 1
SQL> /
CUST_ID COUNT(*)
---------- ----------
1 3
2 3
4 3
5 3
8 3
7 3
9 2
7 rows selected.
You can use a Select Distinct for it.