SQL Server 2005 query, update qtys to 0 where orderid <> min(orderid) - sql-server-2005

I have a table
OrderID Qty ShopID
-----------------------
1 50 10
1 50 11
2 10 15
2 10 18
The person ordered the same order at different shops (they will later decide which one will supply it), but I must only show one qty per order, please help setting the qty = 0 where the orderid is the same and shopid > min(shopID)
e.g.
OrderID Qty ShopID
-----------------------
1 50 10
1 0 11
2 10 15
2 0 18
This is just an example of the real world problem pls

You can try something like this:
;WITH CTE AS
(
SELECT
OrderID, Qty, ShopID,
RowNum = ROW_NUMBER() OVER (PARTITION BY OrderID ORDER BY ShopID DESC)
FROM
dbo.YourOrderTableHere
)
SELECT
OrderID,
OrderedQty = CASE RowNum
WHEN 1 THEN Qty ELSE 0
END,
ShopID
FROM CTE
Basically, I "partition" the data by OrderID - so each row within a given order gets assigned a consecutive RowNum.
In the select from the CTE (Common Table Expression), I return the quantity as stored in the table for the order with RowNum = 1, and I suppress that quantity and return 0 instead for all additional rows for that same OrderID.
This gives me an output of:

Related

BigQuery SQL - Create New Column Based on the Max Value from Multiple Columns

I have a table contains info about customers and their purchases amount of each type of food. I want to create new columns that is the most freq type of food they have purchased. Is there an efficient way to do this?
I tried using case when and do one-to-one comparison, but it got very tedious.
Sample data:
Cust_ID
apple_type1
apple_type2
apple_type3
apple_type4
apple_type5
apple_type6
1
2
0
0
3
6
1
2
0
0
0
1
0
1
3
4
2
1
1
0
1
4
5
5
5
0
0
0
5
0
0
0
0
0
0
--WANT
Cust_ID
freq_apple_type_buy
1
type5
2
type4 and type6
3
type1
4
type1 and type2 and type3
5
unknown
Consider below approach
select Cust_ID, if(count(1) = any_value(all_count), 'unknown', string_agg(type, ' and ')) freq_apple_type_buy
from (
select *, count(1) over(partition by Cust_ID) all_count
from (
select Cust_ID, replace(arr[offset(0)], 'apple_', '') type,cast(arr[offset(1)] as int64) value
from data t,
unnest(split(translate(to_json_string((select as struct * except(Cust_ID) from unnest([t]))), '{}"', ''))) kv,
unnest([struct(split(kv, ':') as arr)])
)
where true qualify 1 = rank() over(partition by Cust_ID order by value desc)
)
group by Cust_ID
if applied to sample data in your question - output is
This uses UNPIVOT to turn your columns in to rows. Then uses RANK() to assign each row a rank, which means if multiple rows are matched in quantity, they share the same rank.
It then selects only the products with rank=1 (possibly multiple rows, if multiple products are tied for first place)
WITH
normalised_and_ranked AS
(
SELECT
cust_id,
product,
qty,
RANK() OVER (PARTITION BY cust_id ORDER BY qty DESC) AS product_rank,
ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY qty DESC) AS product_row
FROM
yourData
UNPIVOT(
qty FOR product IN (apple_type1, apple_type2, apple_type3, apple_type4, apple_type5, apple_type6)
)
)
SELECT
cust_id,
CASE WHEN qty = 0 THEN NULL ELSE product END AS product,
CASE WHEN qty = 0 THEN NULL ELSE qty END AS qty
FROM
normalised_and_ranked
WHERE
(product_rank = 1 AND qty > 0)
OR
(product_row = 1)
Edit: fudge added to ensure row of nulls returned if all qty are 0.
(Normally I'd just not return a row for such customers.)

SQL Split One Row To Multiple Rows Based on Column Number

I have an order table and I will keep it simple. I need to split the rows based on the quantity in the order. For example, if an order quantity is 4 I need to split the original rows into 4 rows with quantity of 1 each. Example data below.
ID FKID Product QTY
1 100 Widget 4
I need a result like this.
ID FKID Product QTY
1 100 Widget 1
2 100 Widget 1
3 100 Widget 1
4 100 Widget 1
Just another option using an ad-hoc tally table and a simple JOIN
Example
Select ID = row_number() over (partition by A.ID order by N)
,FKID
,Product
,Qty = 1
From YourTable A
Join (
Select Top (1000) N=Row_Number() Over (Order By (Select NULL))
From master..spt_values n1 ,master..spt_values n2
) B on N<=A.[QTY]
Returns
ID FKID Product Qty
1 100 Widget 1
2 100 Widget 1
3 100 Widget 1
4 100 Widget 1
One simple method is a recursive CTE:
with cte as (
select ID, FKID, Product, QTY
from t
union all
select ID, FKID, Product, QTY - 1
from t
where qty > 1
)
select id, fkid, product, 1 as qty
from cte;
The only caveat is that if qty can be 100 or greater, you'll need option (maxrecursion 0).

Merge or group rows corresponding to particular column postgresql

I want to group by the resultset further corresponding to the price_type column,
if the data for a product with both price_type variant and parent_product is present, then it must show only the variant one
For example, this data
Product Name PPID QTY PRID PRICE PRICE_TYPE
Shorts 1 10 21 200 variant
Shorts 1 10 21 100 parent_product
Night Suit 1 10 22 200 variant
Night Suit 1 10 22 100 parent_product
Denim 1 10 23 400 parent_product
should come like
Product Name PPID QTY PRID PRICE PRICE_TYPE
Shorts 1 10 21 200 variant
Night Suit 1 10 22 200 variant
Denim 1 10 23 400 parent_product
It seems you want row_number() with conditional ordering:
select *
from (select *, row_number() over (partition by ProductName
order by (case when Price_type = 'variant'
then 0 else 1
end)
) as seq
from table
) t
where seq = 1;
Below is the simple query to get desired result.
select
distinct on(product_name),
t.*
from tab t
order by price_type='variant' desc
You can use a window function:
SELECT * FROM
(
SELECT * ,
RANK() OVER (PARTITION BY product_name ORDER BY priority ) AS rank
FROM (
SELECT *,
CASE
WHEN price_type='variant' THEN 1
ELSE 2
END AS priority
FROM yourtable
) AS X
) AS Y
WHERE rank=1

How can I use SUM() OVER()

I can't understand this code's bug
ID AccountID Quantity
1 1 10 Sum = 10
2 1 5 = 10 + 5 = 15
3 1 2 = 10 + 5 + 2 = 17
4 2 7 = 7
5 2 3 = 7 + 3 = 10
SELECT ID, AccountID, Quantity,
SUM(Quantity) OVER (PARTITION BY AccountID ) AS TopBorcT,
FROM tCariH
Seems like you expected the query to return running totals, but it must have given you the same values for both partitions of AccountID.
To obtain running totals with SUM() OVER (), you need to add an ORDER BY sub-clause after PARTITION BY …, like this:
SUM(Quantity) OVER (PARTITION BY AccountID ORDER BY ID)
But remember, not all database systems support ORDER BY in the OVER clause of a window aggregate function. (For instance, SQL Server didn't support it until the latest version, SQL Server 2012.)
if you are using SQL 2012 you should try
SELECT ID,
AccountID,
Quantity,
SUM(Quantity) OVER (PARTITION BY AccountID ORDER BY AccountID rows between unbounded preceding and current row ) AS TopBorcT,
FROM tCariH
if available, better order by date column.
Query would be like this:
SELECT ID, AccountID, Quantity,
SUM(Quantity) OVER (PARTITION BY AccountID ) AS TopBorcT
FROM #Empl ORDER BY AccountID
Partition by works like group by. Here we are grouping by AccountID so sum would be corresponding to AccountID.
First first case, AccountID = 1 , then sum(quantity) = 10 + 5 + 2 =>
17 & For AccountID = 2, then sum(Quantity) = 7+3 => 10
so result would appear like attached snapshot.

Group By by hiding a column - TSQL

I have a table structure
Table1
ID Hours Qty ProductID
1 2 1 100
1 3 5 200
2 6 6 100
2 2 2 200
If productid is (1,2,3) then i need sum ( Qty * Hours),If productid in (200,300,400,500) then i need sum(qty).
I have written a code like this
select ID,case when productid in (1,2,3) then
SUM( qty * hrs)
when productid in (100,200,300) then SUM( qty ) end result1
from Prod group by id ,productid
but i don't want to group by productid,i would like to pass it in "IN clause".How to achieve it.
Move the SUM() outside of the CASE WHEN statement.
SELECT
ID,
SUM(case when productid in (1,2,3) then qty * hrs
when productid in (100,200,300) then qty
end) result1
FROM
Prod
GROUP BY
ID
Assuming you want all columns plus the result of your query, you can do this:
select p.*, aux.result
from Prod p
inner join (select ID,case when productid in (1,2,3) then SUM( qty * hrs)
when productid in (100,200,300) then SUM( qty )
end as result
from Prod group by id ,productid) aux on aux.id = p.id