I have a column for price. I need to select the price based on another column called status. If status is p then select that price first else select price from other status h. I need to make sure that query selects the price if status is p first when both status P & h are available.
You can use Rank function (if your DBMS supports), which will group the rows based on product and rank the sub group rows based on status. then you can apply where clause to select first rank rows from each sub-group. the query will look like below for MS sql-server.
select price
, [status]
, product
from
(select price
, [status]
, product
, RANK() over (PARTITION BY product
order by case
when [status]='p' then 1
else 0
end desc
) as rnk
from #tableA) Q
where rnk =1
Sample Input
Output
Related
I am newbie to Sql, I want to get SUM of a particular column from a table and also the value of another Column from the table which is in the last row of column used in SUM.
For Eg:
Below is my Table I want sum of all amount fields where Code is 1 and and also a qty field which is at the last occurrence of code with value 1 in table
Table Image
I want some thing like below
select SUM(amount) from table where Code = 1 UNION ALL Select qty from test where Code = 1 and id = MAX(id) for/where code = 1 ;
If I get you correctly your need something like following, here is the demo.
select
code,
total_amount,
qty
from
(
select
code,
sum(amount) over (order by id) as total_amount,
qty,
row_number() over (partition by code order by id desc) as rnk
from yourTable
where code = 1
) val
where rnk =1
Output:
*-----------------------*
|code total_amount qty |
*-----------------------*
| 1 80 20 |
*-----------------------*
You can do this without a subquery, if you want:
select distinct top (1) sum(amount) over () as amount, qty
from t
where code = 1
order by id desc;
Folks at a loss here!!!
First, this is what I am trying to achieve:
Select all the records from table CUSTOMER_ORDER_DETAILS table shown below and if multiple entries for the same CUSTOMER_NO exist then:
- select the entry with PAID = 1
- if there are multiple PAID = 1 entries, then select the record with TYPE = Y
Expected Result:
877, CU115, lit, 0, 1, X
878, CU111, Toi, 1, 1, Y
879, CU117, Fla, 1, 1, X
My approach was to get the count(CUSTOMER_NO) > 1 using GROUP BY on CUSTOMER_NO, but as soon as I am adding the remaining columns of the table to the Select statement, the count column is showing a value of 1.
Any pointers to tackle this or implement if-else kind of logic?
This is a prioritization query. Here is one method to do what you want:
select t.*
from (select t.*,
row_number() over (partition by customer_no
order by paid desc, type desc
) as seqnum
from t
) t
where seqnum = 1;
This assumes that paid takes on the values 0 and 1, and that type has the values X and Y.
You can prioritize these conditions with an order by condition in row_number function.
select * from (
select t.*,
row_number() over(partition by customer_no
order by case when paid=1 and type='Y' then 1
when paid=1 then 2
else 3 end) as rnum
from customer_orders t
) t
where rnum=1
This assumes there can only be one row with type='Y' per customer_no if there exist multiple rows with paid=1 for that same customer_no.
If there exist multiple rows with paid =1 and all of them have a type <> 'Y' then a row is arbitrarily picked amongst them.
I have a table which contains these columns;
CODE
PRICE
DATE
So what i want to do is to get last 3 distinct price values per id ordered by date column. Basically the most recent 3 distinct prices per id.
Also there is an ID column in the table. It is the primary key of the table.
Edit: As ughai said, DISTINCT doesn't work with row_number.
Select t.id , c.Price
from TableName t
CROSS APPLY (
SELECT TOP 3 Price
FROM TableName s
WHERE s.ID = t.ID
ORDER BY [DATE] DESC
) c (Price)
GROUP BY t.id , c.Price
Is there a way to change "LIMIT 1" and get the same output? I have to get client's name, surname and a quantity of books that has the most books
SELECT stud.skaitytojas.name, stud.skaitytojas.surname,
COUNT (stud.skaitytojas.nr) AS quantity
FROM stud.egzempliorius , stud.skaitytojas
WHERE stud.egzempliorius.client = stud.skaitytojas.nr
GROUP BY stud.skaitytojas.nr
ORDER BY quantity DESC
LIMIT 1
Postgres supports the ANSI standard FETCH FIRST 1 ROW ONLY, so you can do:
SELECT s.name, s.surname, COUNT(s.nr) AS quantity
FROM stud.egzempliorius e JOIN
stud.skaitytojas s
ON e.client = s.nr
GROUP BY s.name, s.surname
ORDER BY quantity DESC
FETCH FIRST 1 ROW ONLY;
Also notice the use of table aliases and proper JOIN syntax. I also prefer to list the columns in the SELECT in the GROUP BY, although that is optional if s.nr is unique.
You can select the row with the highest quantity using row_number()
SELECT * FROM (
SELECT * , row_number() over (order by quantity desc) rn FROM (
SELECT stud.skaitytojas.name, stud.skaitytojas.surname, COUNT (stud.skaitytojas.nr) AS quantity
FROM stud.egzempliorius , stud.skaitytojas
WHERE stud.egzempliorius.client = stud.skaitytojas.nr
GROUP BY stud.skaitytojas.name, stud.skaitytojas.surname
) t
) t where rn = 1
If you want to include ties for the highest quantity, then use rank() instead.
I want to write a stored procedure.
In that stored procedure, I want to find duplicate row values from a table, and calculate sum operation on these rows to the same table.
Let's say, I have a CustomerSales table;
ID SalesRepresentative Customer Quantity
1 Michael CustA 55
2 Michael CustA 10
and I need to turn table to...
ID SalesRepresentative Customer Quantity
1 Michael CustA 65
2 Michael CustA 0
When I find SalesRepresentative and Customer duplicates at the same time, I want to sum all Quantity values of these rows and assign to the first row of a table, and others will be '0'.
Could you help me.
To aggregate duplicates into one row:
SELECT min(ID) AS ID, SalesRepresentative, Customer
,sum(Quantity) AS Quantity
FROM CustomerSales
GROUP BY SalesRepresentative, Customer
ORDER BY min(ID)
Or, if you actually want those extra rows with 0 as Quantity in the result:
SELECT ID, SalesRepresentative, Customer
,CASE
WHEN (count(*) OVER (PARTITION BY SalesRepresentative,Customer)) = 1
THEN Quantity
WHEN (row_number() OVER (PARTITION BY SalesRepresentative,Customer
ORDER BY ID)) = 1
THEN sum(Quantity) OVER (PARTITION BY SalesRepresentative,Customer)
ELSE 0
END AS Quantity
FROM CustomerSales
ORDER BY ID
This makes heavy use of window functions.
Alternative version without window functions:
SELECT min(ID) AS ID, SalesRepresentative, Customer, sum(Quantity) AS Quantity
FROM CustomerSales
GROUP BY SalesRepresentative, Customer
UNION ALL
SELECT ID, SalesRepresentative, Customer, 0 AS Quantity
FROM CustomerSales c
GROUP BY SalesRepresentative, Customer
LEFT JOIN (
SELECT min(ID) AS ID
FROM CustomerSales
GROUP BY SalesRepresentative, Customer
) x ON (x.ID = c.ID)
WHERE x.ID IS NULL
ORDER BY ID