Insert missing row(s) - sql

I have a table of supply/price curve, where for some items the zero price row is missing, and I want to insert that row for those items. The table looks like this:
Item Point Price Quantity
-----------------------------
A 1 0 0
A 2 100 5
A 3 200 10
B 1 50 6
B 2 70 8
The number of rows per item can be different (like 3 points for item A, and less or more points for another item). In the above, the zero price and quantity point is missing for item B, so the updated table should look like this:
Item Point Price Quantity
-----------------------------
A 1 0 0
A 2 100 5
A 3 200 10
B 1 0 0
B 2 50 6
B 3 70 8
Where a new row (point with zero price/quantity) is added and point of the other rows is updated. The new row should be added for all items where point 1 is not Price=0 and Quantity = 0. How to do it in Oracle sql server?

Hmmm, you can do this in two steps. First, I would insert point with a value of 0 and then increment the value:
insert into t(item, point, price, quantity)
select item, 0 as point, 0 as price, 0 as quantity
from t
group by item
having min(price) <> 0;
Then, increment the point column:
update t
set point = point + 1
where exists (select 1 from t t2 where t2.item = t.item and t2.point = 0);
commit;

Related

Show two different sum columns based on a single column

Show two different sum columns based on another column.
For this table:
ID Item Quantity Location
1 1 10 A
2 1 10 B
3 1 10 A
4 2 10 A
5 2 10 A
6 2 10 B
7 3 10 A
8 3 20 A
I need to see the total quantities for both location A and location B (to compare which is higher), but only for items that have a location B:
Expected result:
Item Quantity A Quantity B
1 20 10
2 20 10
I've been trying this but getting errors:
SELECT st.item, st.qty ALIAS(stqty),
(SELECT SUM(dc.qty)
FROM table dc
WHERE st.item = dc.item) ALIAS(dcqty))
FROM table st
WHERE location ='b'
I can do this easily with two queries obviously, but I was hoping for a way to do it in one.
you can use a sum with case statement to do your pivot then a having to exclude rows with no total for b
here is the fiddle
https://www.db-fiddle.com/f/rS8fgvWoFxn879Utc2CKbu/0
select Item,
sum(case when Location = 'A' then Quantity else 0 end),
sum(case when Location = 'B' then Quantity else 0 end)
from myTable
group by Item
having sum(case when Location = 'B' then Quantity else 0 end) > 0

Replace a column value with random values

I want to replace values in a column with randomized values
NO LINE
-- ----
1 1
1 2
1 3
1 4
2 1
2 2
3 1
4 1
4 2
I want to randomize column NO and replace with random values. I have 5 million records and doing something like below script gives me 5 million unique NO's but as you can see NO is not unique and i want the same random value assigned for the same NO.
UPDATE table1
SET NO= abs(checksum(NewId())) % 100000000
I want my resultant dataset like below
NO LINE
------ ----
99 1
99 2
99 3
99 4
1092 1
1092 2
3456 1
41098 1
41098 2
I would recommend rand() with a seed:
UPDATE table1
SET NO = FLOOR(rand(NO) * 100000000);
This runs a slight risk of collisions, so two different NO rows could get the same value.
If the numbers do not need to be "random" you can give them consecutive values in an arbitrary order and avoid collisions:
with toupdate as (
select t1.*,
dense_rank() over (order by rand(NO), no) as new_no
from t
)
update toupdate
set no = new_no;

Inserting a new indicator column to tell if a given row maximizes another column in SQL

I currently have a table in SQL that looks like this
PRODUCT_ID_1 PRODUCT_ID_2 SCORE
1 2 10
1 3 100
1 10 3000
2 10 10
3 35 100
3 2 1001
That is, PRODUCT_ID_1,PRODUCT_ID_2 is a primary key for this table.
What I would like to do is use this table to add in a row to tell whether or not the current row is the one that maximizes SCORE for a value of PRODUCT_ID_1.
In other words, what I would like to get is the following table:
PRODUCT_ID_1 PRODUCT_ID_2 SCORE IS_MAX_SCORE_FOR_ID_1
1 2 10 0
1 3 100 0
1 10 3000 1
2 10 10 1
3 35 100 0
3 2 1001 1
I am wondering how I can compute the IS_MAX_SCORE_FOR_ID_1 column and insert it into the table without having to create a new table.
You can try like this...
Select PRODUCT_ID_1, PRODUCT_ID_2 ,SCORE,
(Case when b.Score=
(Select Max(a.Score) from TableName a where a.PRODUCT_ID_1=b. PRODUCT_ID_1)
then 1 else 0 End) as IS_MAX_SCORE_FOR_ID_1
from TableName b
You can use a window function for this:
select product_id_1,
product_id_2,
score,
case
when score = max(score) over (partition by product_id_1) then 1
else 0
end as is_max_score_for_id_1
from the_table
order by product_id_1;
(The above is ANSI SQL and should run on any modern DBMS)

SQL decrement a value based on two columns till 0

I have the following datasets (just a sample):
Table1:
ID MAX AMT SORTED
1 20 0 1
1 30 0 2
1 40 0 3
1 50 0 4
2 0 0 1
2 30 0 2
2 40 0 3
2 40 0 4
...
Table2:
ID AMT
1 75
2 70
...
I must update Table1.AMT from Table2.AMT using this rules:
Table1 and Table2 are joined on ID
Table1.AMT can't hold larger value than MAX
if Table2.AMT >= Table1.MAX then Table1.AMT = Table1.MAX... then on the next row update Table1.AMT with Table2.AMT - previous record AMT still using the above rules.
So the expected output would be
ID MAX AMT SORTED
1 20 20 1
1 30 30 2
1 40 25 3
1 50 0 4
2 0 0 1
2 30 30 2
2 40 40 3
2 40 0 4
...
How can one achieve that?
I thought of creating a temp table with an aggregated SUM() of Table1.MAX, and using that as a reference to update Table1.AMT (if SUM(MAX) < Table2.AMT then Table1.AMT = Table1.MAX else Table1.AMT = previous records SUM(MAX)).
But can it be done without a temp table? (Sadly I can't create functions and procedures in my work env.)
More efficient solution can be made using specifics or Oracle PL/SQL.
Here is a generic solution:
select t1.ID, min(t1.MAX) as MAX, least(min(t1.MAX),coalesce(min(t2.AMT),0)-coalesce(least(sum(t1p.MAX-t1p.AMT), min(t2.AMT)),0)+min(t1.AMT)) as AMT, t1.SORTED
from Table1 t1
left join Table2 t2 on t2.ID = t1.ID
left join Table1 t1p on t1p.ID = t1.ID and t1p.SORTED < t1.SORTED
group by t1.ID, t1.SORTED
order by t1.ID, t1.SORTED
explanation of calculating AMT:
AMT is smallest of "MAX for the row" and "How much is possible"
least(min(t1.MAX),"How much is possible")
"How much is possible": max available - how much was given for previous rows + how much we already have
coalesce(min(t2.AMT),0) - "how much was given for previous rows" + min(t1.AMT)
"how much was given for previous rows": smalles of how much required to fill and how much possible
coalesce(least(sum(t1p.MAX-t1p.AMT), min(t2.AMT)),0)

Reading through a table row by row in SQL Server 2000

I have a table that I want to read row by row to search for a specific match.
Here are the result of my table and the columns. Pos_Scan represents what is scanned at the point of sale and how many
UniqueID INGREDINETID KITCHENITEMID QUANTITY POS_SCAN STATUS
1 510 0111 1 5 0
2 54491472 0111 1 2 0
3 6001069201906 6006749006031 1 0 0
4 54491472 6006749006031 1 5 0
HAS more than these records here what i want to do is to be able to loop through this table and pull out rows that have the same kitchenitemid and have pos_scan >= quantity this is to form a complete recipe for example row 1 and 2 will be a complete recipe but row 3 and 4 will not be a recipe because pos_scan for ingredientid at uniqueid 3 is 0
please help me
thank you
If my reconstructed requirement suggestions in the comments are close to right, then something like the following would do:
SELECT
KitchenItemID,MIN(Satisfied),MAX(Satisfied)
FROM
(
SELECT
KitchenItemID,
CASE WHEN pos_scan >= Quantity THEN 1 ELSE 0 END as Satisfied
FROM
OriginalTableNotNamdInQuestion
) t
GROUP BY
KitchenItemID
HAVING
MIN(Satisfied) = MAX(Satisfied) --Change this to < to find incomplete "recipes"