I have a table with Article_code, Date, And Quantity.
What I try is to find where for the same article the quantity had an increase or a decrease of 10 times compared to the previous date.
For instance, I have following columns
Article Date Quantity X10
1001 20-01-2015 22
1001 21-02-2016 220
For the row with quantity 220 should be marked as x in column x10.
What I tried is the following
UPDATE ph
SET [X10] = 'Px10'
FROM
[dbo].[Sales] ph
inner join [dbo].[Sales] t on (ph.[Article] = t.[Article])
WHERE
ph.[quantity] / t.[quantity] = 10
OR
t.[quantity] / ph.[quantity] = 10;
Try the following:
select *,
case when exists
(
select 1
from yourtable t2
where dateadd(day,-1,t1.[Date])=t2.[Date]
and t1.Quantity>=10*t2.Quantity
) then 'x' else '' end as 'x10'
from youttable t1
Try this.
UPDATE s
SET s.x10 = 'x'
FROM Sales s
OUTER APPLY ( SELECT TOP 1 quantity
FROM sales s2
WHERE s2.Article_code = s.Article_code
AND s2.date < s.date
ORDER BY s2.date DESC ) t
WHERE s.quantity = 10 * t.quantity;
Related
There is a field in the sql query that I can't do. First of all, a new column must be added to the table below. The value of this column needs to be percent complete, so it's a percentage value. So for example, there are 7 values from Cupboard=1 shelves. Where IsCounted is here, 3 of them are counted. In other words, those with Cupboard = 1 should write the percentage value of 3/7 as the value in the new column to be created. If the IsCounted of the others is 0, it will write zero percent. How can I do this?
My Sql Code:
SELECT a.RegionName,
a.Cupboard,
a.Shelf,
(CASE WHEN ToplamSayım > 0 THEN 1 ELSE 0 END) AS IsCounted
FROM (SELECT p.RegionName,
r.Shelf,
r.Cupboard,
(SELECT COUNT(*)
FROM FAZIKI.dbo.PM_ProductCountingNew
WHERE RegionCupboardShelfTypeId = r.Id) AS ToplamSayım
FROM FAZIKI.dbo.DF_PMRegionType p
JOIN FAZIKI.dbo.DF_PMRegionCupboardShelfType r ON p.Id = r.RegionTypeId
WHERE p.WarehouseId = 45) a
ORDER BY a.RegionName;
The result is as in the picture below:
It looks like a windowed AVG should do the trick, although it's not entirely clear what the partitioning column should be.
The SELECT COUNT can be simplified to an EXISTS
SELECT a.RegionName,
a.Cupboard,
a.Shelf,
a.IsCounted,
AVG(a.IsCounted * 1.0) OVER (PARTITION BY a.RegionName, a.Cupboard) Percentage
FROM (
SELECT p.RegionName,
r.Shelf,
r.Cupboard,
CASE WHEN EXISTS (SELECT 1
FROM FAZIKI.dbo.PM_ProductCountingNew pcn
WHERE pcn.RegionCupboardShelfTypeId = r.Id
) THEN 1 ELSE 0 END AS IsCounted
FROM FAZIKI.dbo.DF_PMRegionType p
JOIN FAZIKI.dbo.DF_PMRegionCupboardShelfType r ON p.Id = r.RegionTypeId
WHERE p.WarehouseId = 45
) a
ORDER BY a.RegionName;
I have two tables one is Base_table and another one is Txn_table as follows
Base_table
Person | Amount
----------------
P1 300
p2 200
p3 100
Txn_table
Person | txn_type | Amount
---------------------------------
P1 Debit 200
P2 Credit 200
P3 Debit 100
P1 Credit 400
I need to update Base_Table based on Txn_table data like P1 has done Debit and Credit ,the total calculation is something like (Credit-Debit) = (400-200) = 200,and already P1 is having 300 in Base_table so total 300 + 200 = 500 value needs to be updated in Base_Table for P1.in the same way for others as well please help me to write the Oracle SQL query
And the data should be like this in Base_table after updation.
Base_table
Person | Amount
P1 500
p2 400
p3 0
Note: here I should not go for PLsql Block only i need to perform this updation using SQL query.
An inline correlated subquery might get the job done:
UPDATE base_table b
SET b.amount =
b.amount
+ NVL(
(SELECT SUM(DECODE(t.txn_type, 'Credit', 1, -1) * t.amount)
FROM txn_table t
WHERE t.person = b.person
), 0)
In Oracle, a typical way to update one table from another is to use correlated subqueries:
update base_table b
set amount = b.amount +
(select sum(case when t.txn_type = 'Credit' then t.amount else - t.amount end)
from txn_table t
where t.person = b.person
)
where exists (select 1
from txn_table t
where t.person = b.person
having sum(case when t.txn_type = 'Credit' then t.amount else - t.amount end) <> 0
);
Just to suggest an other approach.
merge into base_table tt
using
( select person , sum( decode(upper(txn_type) ,
'CREDIT', + AMOUNT ,
'DEBIT', - AMOUNT
) ) as final
from Txn_table
group by person ) b
on ( tt.person = b.person )
when matched then
update set tt.AMOUNT = tt.AMOUNT + b.final
I've a table with the following rows of data.
EngID Tower Billing Amt
100 ICS Y 5000
100 EDT Y 7777
100 ICS N 2000
and I want the result set to be consolidated by Tower & Eng ID and the amount put into the appropriate column (Invoiced or Not Invoiced) based on Billing criteria. So, below is how the final result set should look for the above table:
EngID Tower Inv Amt (Amt when Billing = Y) Non-Invoiced Amt (Billing=N)
100 ICS 5000 2000
100 EDT 7777
I'm able to get the 1st row of the result set by using the below query:
Select Temp1.Tower, Temp1. EngID, Temp2.InvoiceAmt as [Inv Amt], Temp1.InvoiceAmt AS [Non-Invoiced Amt] from
(
SELECT EngID, TOWER,BILLING, InvoiceAmt,RANK() OVER (PARTITION BY EngID, TOWER ORDER BY BILLING) AS RNK
FROM [GDF].[dbo].[Sample] ) Temp1 INNER JOIN (SELECT EngID, TOWER,Billing,InvoiceAmt, RANK() OVER (PARTITION BY EngID, TOWER ORDER BY BILLING) AS RNK
FROM [GDF].[dbo].[Sample] ) Temp2 ON
Temp1.EngID = Temp2.EngID
AND (Temp1.Tower = Temp2.Tower AND Temp1.Billing < Temp2.Billing)
However, struggling to get the second row result. My plan is to get the two rows through two separate queries and then do a union to combine the results.
One method is conditional aggregation:
select s.engid, s.tower,
sum(case when s.billing = 'Y' then amt end) as billing_y,
sum(case when s.billing = 'N' then amt end) as billing_n
from gdf.dbo.sample s
group by s.engid, s.tower;
Try this:
select engid, tower,
sum(case when billing = 'Y' then amt end) Inv_amt,
sum(case when billing = 'N' then amt end) Non_Inv_amt,
from my_table
group by
engid,
tower;
We can also do it using OUTER APPLY as below:
select A.EngID,
sum(A.Amt) as [Inv Amt (Amt when Billing = Y)],
sum(B.Amt) as [Non-Invoiced Amt (Billing=N)]
from #test A
outer apply(select b.Amt from #test B where A.EngID = b.EngID and b.tower = a.tower and B.Billing = 'n') B
where a.billing = 'y'
group by A.EngID, A.Tower
Simple LEFT JOIN:
select A.EngID,
sum(A.Amt) as [Inv Amt (Amt when Billing = Y)],
sum(B.Amt) as [Non-Invoiced Amt (Billing=N)]
from #test A
left join #test B on A.EngID = b.EngID
and b.tower = a.tower
and B.Billing = 'n'
where a.billing = 'y'
group by A.EngID, A.Tower
This code will give the desired result without any complexity.Please do find the snapshot of output from below mentioned query.Hope I solved your problem.
WITH Mycte
AS
(
Select ENGID,Tower,Case When Billing='Y' Then ISNULL(SUM(Amt),0) END AS Inv_Amt,
Case When Billing='N' Then ISNULL(SUM(Amt),0) END AS Non_Inv_Amt from #Sample
group by ENGID,Tower,Billing
)
Select ENGID,Tower,SUM(Inv_Amt) AS Inv_Amt,SUM(Non_Inv_Amt) AS Non_Inv_Amt from mycte
group by ENGID,Tower
I have prepared a sqlfiddle workspace which you can see the question and solve it easily.
There is a table include ID, DAT, AMN, FLWC, FLWD, TYP.
I would like to sort table by DAT and ID (DAT is first keyword in sort)
then update FLWC and FLWD from previous record depend on TYP.
for example if 0:previous record and 1:current record then:
if typ1==d then (flwc1=flwc0 AND flwd1=flwd0+amn1)
if typ1==c then (flwc1=flwc0+amn AND flwd1=flwd0)
You can see that flwc and flwd will be set to next record and one of them will be sum to AMN depend on TYP value.
Table before changes:
-- id__dat__amn__flwc__flwd__typ
-- 1 10 100 0 0 d
-- 2 11 200 0 0 c
-- 3 12 300 0 0 d
-- 4 13 400 0 0 c
-- 5 14 500 0 0 d
-- 6 15 600 0 0 c
-- 7 16 700 0 0 d
Table after UPDATE:
-- id__dat__amn__flwc__flwd__typ
-- 1 10 100 0 100 d
-- 2 11 200 200 100 c
-- 3 12 300 200 400 d
-- 4 13 400 600 400 c
-- 5 14 500 600 900 d
-- 6 15 600 1200 900 c
-- 7 16 700 1200 1600 d
Please note that in real test the DAT fields might be equal in several records because DAT means DATE.
I have checked some answer from others but they don't have condition in their answers.
Live test: sqlfiddle
Complicated question but easy answer! (it shows that the start point is very important to thinking about a question)
declare #sumc decimal
declare #sumd decimal
set #sumc=0
set #sumd=0
update myTable set
#sumc+= case typ when 'c' then amn else 0 end, flwc=#sumc,
#sumd+= case typ when 'd' then amn else 0 end, flwd=#sumd
You should add two more column with bit values i.e. C and D. Value of C is one if typ is c and 0 if typ is d and in reverse for d.
for over i
{
flwc(i)=flwc(i-1)+amn*C(i)
flwd(i)=flwd(i-1)+amn*D(i)
}
---------------------------------- Edit ---------------------------------
This is pseudo-code of what you have to do. In SQL doing it requires some consecutive queries to be done.
In C#
//Initiation
SqlConnection Con=new SqlConnection(Some_Connection_String);
SqlCommand Comm=new SqlCommand("",Con);
Con.Open();
Comm.CommandText="SELECT TOP (1) id FROM table_name ORDER BY id DESC";
int MaxId=(int)Comm.ExecuteScaler();
int flwc=0,flwd=0;
int amn=0;
string typ="";
//Itteration
for (int Id=1;Id<MaxId;Id++)
{
Comm.CommandText = "UPDATE table_name SET flwc="+(flwc+amn*(typ=="c"?1:0)).ToString()+",flwd="+(flwd+amn*(typ=="d"?1:0)).ToString()+" WHERE id="+Id.ToString();
Comm.ExecuteNonQuery();
//Update
Comm.CommandText = "SELECT * FROM table_name WHERE id="+Id.ToString();
reader=Comm.ExecuteReader();
reader.Read();
amn=reader.GetInt32(2);
flwc=reader.GetInt32(3);
flwd=reader.GetInt32(4);
typ=reader.GetString(5);
}
Con.Close();
If I have no syntax or logical errors (!) this should work fine.
If you want to update your table with sql in SQL Server you can do something like this:
i use two updates for your table and in the first one update the columns with amn and 0
with tab as
(select
id,dat,amn,(select max(id) from mytable) as maxid,
case when typ = 'd' then 0 else amn end as flwc,
case when typ = 'c' then 0 else amn end as flwd,
typ,
0 as rn,0 as totalc,0 as totalD
from mytable)
update mytable set
mytable.flwc = tab.flwc,mytable.flwd = tab.flwd
from mytable inner join tab on mytable.id = tab.id;
in the second one sum them:
with tab2 as
(select
t1.id,t1.dat,x.d
from mytable t1
CROSS APPLY (SELECT SUM(v)
FROM ( SELECT TOP(select count(*) from mytable) b.flwd
FROM mytable b
WHERE b.id <= t1.id
ORDER BY b.id DESC ) x(v)
) x(d)),
tab3 as
(select
t1.id,t1.dat,x.c
from mytable t1
CROSS APPLY (SELECT SUM(v)
FROM ( SELECT TOP(select count(*) from mytable) b.flwc
FROM mytable b
WHERE b.id <= t1.id
ORDER BY b.id DESC ) x(v)
) x(c)),
tab4 as (select tab2.id,tab2.dat,tab2.d,tab3.c from tab2,tab3 where tab2.id = tab3.id),
tab5 as (select t4.id,t4.dat,t4.amn,tab4.c as flwc,tab4.d as flwd,t4.typ
from mytable t4,tab4
where t4.id = tab4.id)
update mytable set
mytable.flwc = tab5.flwc,mytable.flwd = tab5.flwd
from mytable inner join tab5 on mytable.id = tab5.id;
SQL Fiddle
I have a table in Microsoft Dynamics AX ERP Database of SQL Server 2008 R2, which has some rows, there is a field named qty in table, some rows have negative qty and some rows have positive quantity. There is another field TransactionID, now I want to select all those TransactionIDs which have negative qty, AND also those TransactionIDs which have some rows with positive QTys and negative qtys too.
TransactionID is a foreign key field of a master table.
So far I wrote below code which is not working.
select * from RBOTRANSACTIONSALESTRANS main where main.qty < 0
and main.DATAAREAID = 'DAT'
and exists
(
select 1 from RBOTRANSACTIONSALESTRANS where QTY > 0
and RBOTRANSACTIONSALESTRANS.DATAAREAID = main.DATAAREAID
and RBOTRANSACTIONSALESTRANS.STORE = main.STORE
and RBOTRANSACTIONSALESTRANS.TERMINALID = main.TERMINALID
)
order by main.TRANSACTIONID
A recap, you want to select all rows for which there exists at least one row with the same TransactionID that has a negative quantity?
select *
from RBOTRANSACTIONSALESTRANS main
where main.DATAAREAID = 'DAT'
and exists
(
select 1
from RBOTRANSACTIONSALESTRANS sub
where sub.QTY < 0
and sub.DATAAREAID = main.DATAAREAID
and sub.STORE = main.STORE
and sub.TERMINALID = main.TERMINALID
and sub.TRANSACTIONID = main.TRANSACTIONID
)
order by main.TRANSACTIONID
The main difference is, that you had a main.QTY < 0 check. And I added sub.TRANSACTIONID = main.TRANSACTIONID.
more or less the query should be like that
select * from
(
select tansactionID, sum(qty) as q, sum(abs(qty)) as q2
from table2 T
group by tansactionID ) T
where q<> q2
post the schema so i can adjust it
JOINed query defines TRANSACTIONID according your conditions (see HAVING conditions). So after JOIN you filter your table to leave only these TRANSACTIONID.
select t.* from RBOTRANSACTIONSALESTRANS t
join
(
select TRANSACTIONID,min(main.qty),max(main.qty)
from RBOTRANSACTIONSALESTRANS main
GROUP BY TRANSACTIONID
HAVING (max(main.qty) < 0)
or
((min(main.qty) < 0) and (max(main.qty) > 0))
) t1 on (t.TRANSACTIONID=t1.TRANSACTIONID)
UPD After you comment under your question I think you need to use only this condition in the inner query:
HAVING not (min(main.qty) < 0)
It seems to me that you may be over complicating the issue. If I am understanding the criteria correctly you want All rows where
the quantity is < 0
OR
the quantity is < 0 AND a row exists with the same transaction ID
with a negative quantity
So to start
SELECT *
FROM RBOTRANSACTIONSALESTRANS tr
WHERE tr.DATAAREAID = 'DAT'
AND tr.Qty < 0
Would satisfy the first criterion. The following would do the second.
SELECT *
FROM RBOTRANSACTIONSALESTRANS tr
WHERE tr.DATAAREAID = 'DAT'
AND tr.Qty > 0
AND EXISTS
( SELECT 1
FROM RBOTRANSACTIONSALESTRANS neg
WHERE neg.TransactionID = tr.TransactionID
AND neg.DATAAREAID = 'DAT'
AND neg.Quantity < 0
)
This can be combined as
SELECT *
FROM RBOTRANSACTIONSALESTRANS tr
WHERE tr.DATAAREAID = 'DAT'
AND ( tr.Qty < 0
OR EXISTS
( SELECT 1
FROM RBOTRANSACTIONSALESTRANS neg
WHERE neg.TransactionID = tr.TransactionID
AND neg.DATAAREAID = 'DAT'
AND neg.Quantity < 0
)
)
However, the first clause is redundant since any row where the quantity is < 0 will also be satisfied by the EXISTS clause. So this can be simplified to:
SELECT *
FROM RBOTRANSACTIONSALESTRANS tr
WHERE tr.DATAAREAID = 'DAT'
AND EXISTS
( SELECT 1
FROM RBOTRANSACTIONSALESTRANS neg
WHERE neg.TransactionID = tr.TransactionID
AND neg.DATAAREAID = 'DAT'
AND neg.Quantity < 0
)