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
)
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 the following select statement in Redshift that will return rows with certain values if the condition inside is met. I want to transform this into a DQ check which will return 1 (True) if no rows ae returned or 0 if any row is returned, but I do not know where I should apply the case statement.
Here is the select statement:
select * from (select brand,calendar_dt, product,
count(account) count from revenue_base
where player_days = 0 and volume_loc >0 group by brand,calendar_dt, product)
where count > 1000 and calendar_dt >='2020-07-12'
and calendar_dt < '2020-07-13'
Can you please offer me some ideas for this?
You may try using exists logic here:
select
case when not exists (
select 1 from
(
select brand, calendar_dt, product, count(account) as count
from revenue_base
where player_days = 0 and volume_loc > 0
group by brand, calendar_dt, product
) t
where calendar_dt >= '2020-07-12' and calendar_dt < '2020-07-13' and
count > 1000
)
then 1 else 0 end as result;
First, Redshift supports booleans, so case is not needed. Second, do the filtering on the date before the aggregation. This is usually faster.
Then, you can filter by the count using a having clause, so no subquery is needed:
select not exists (select 1
from revenue_base
where player_days = 0 and volume_loc > 0 and
calendar_dt >= '2020-07-12' and calendar_dt < '2020-07-13'
group by brand, calendar_dt, product
having count(*) > 1000
) as result
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;
i have table of lucky draw option where two types of option is there one is Stock Qty options and second option is General option
now i have to check the stock qty before i get the random option
i have write the query as below
set #percentage = 100 * rand();
select bkt_lucky_option.*,bkt_lucky_option_stock.option_stock_qty
from bkt_lucky_option LEFT JOIN bkt_lucky_option_stock ON bkt_lucky_option.lucky_option_id = bkt_lucky_option_stock.option_lucky_id
WHERE bkt_lucky_option_stock.option_stock_qty > 0
order by bkt_lucky_option.lucky_option_in_hour <= #percentage, rand()
limit 0, 8
WHERE bkt_lucky_option_stock.option_stock_qty > 0
For this condition i have to check if lucky_option_type is 1 then only i this condition should apply
WHERE lucky_option_type != 1 OR bkt_lucky_option_stock.option_stock_qty > 0
If you are using SQL server then try below query :
SET #percentage = 100 * rand();
SELECT bkt_lucky_option.*,bkt_lucky_option_stock.option_stock_qty
FROM bkt_lucky_option
LEFT JOIN bkt_lucky_option_stock ON bkt_lucky_option.lucky_option_id =
bkt_lucky_option_stock.option_lucky_id
WHERE ( bkt_lucky_option_stock.option_stock_qty > 0 AND lucky_option_type =
1 ) OR
( bkt_lucky_option_stock.option_stock_qty =
bkt_lucky_option_stock.option_stock_qty AND lucky_option_type <> 1
)
ORDER BY bkt_lucky_option.lucky_option_in_hour <= #percentage, RAND()
limit 0, 8
I have a table of items by date (each row is a new date). I am drawing out a value from another column D. I need it to replace 0s though. I need the following logic: when D=0 for that date, use the value in column D from the date prior.
Actually, truth be told, I need it to say, when D is 0, use the value from the latest date where D was not a 0, but the first will get me most of the way there.
Is there a way to build this logic? Maybe a CTE?
Thank you very much.
PS I'm using SSMS 2008.
EDIT: I wasn't very clear at first. The value I want to change is not the date. I want change the value in D with the latest non-zero value from D, based on date.
May be the following query might help you. It uses the OUTER APPLY to fetch the results. Screenshot #1 shows the sample data and query output against the sample data. This query can be written better but this is what I could come up with right now.
Hope that helps.
SELECT ITM.Id
, COALESCE(DAT.New_D, ITM.D) AS D
, ITM.DateValue
FROM dbo.Items ITM
OUTER APPLY (
SELECT
TOP 1 D AS New_D
FROM dbo.Items DAT
WHERE DAT.DateValue < ITM.DateValue
AND DAT.D <> 0
AND ITM.D = 0
ORDER BY DAT.DateValue DESC
) DAT
Screenshot #1:
UPDATE t
Set value = SELECT value
FROM table
WHERE date = (SELECT MAX(t1.date)
FROM table t1
WHERE t1.value != 0
AND t1.date < t.date)
FROM table t
WHERE t.value = 0
You could maybe something like this as part of an update script...
SET myTable.D = (
SELECT TOP 1 myTable2.D
FROM myTable2
WHERE myTable2.myDateField < myTable.myDateField
AND myTable2.D != 0
ORDER BY myTable2.myDateField DESC)
That's assuming that you want to actually update the data though rather than just replace the values for the purpose of a select query.
How about:
SELECT
i.ID,
i.DateValue,
D = CASE WHEN I.D <> 0 THEN I.D ELSE X.D END
FROM
Items I
OUTER APPLY (
SELECT TOP 1 S.D
FROM Items S
WHERE S.DATEVALUE < I.DATEVALUE AND S.D <> 0
ORDER BY S.DATEVALUE DESC
) X
SELECT t.id,
CASE WHEN t.D = 0 THEN t0.D
ELSE t.D END
FROM table AS t
LEFT JOIN table AS t0
ON t0.time =
(
SELECT MAX(time) FROM t0
WHERE t0.time < t.time
AND t0.D != 0
)
or if you want to avoid aggregates entirely,
SELECT t.id,
CASE WHEN t.D = 0 THEN t0.D
ELSE t.D END
FROM table AS t
LEFT JOIN table AS t0
ON t0.time < t.time
LEFT JOIN table AS tx
ON tx.time > t0.time
WHERE t0.D != 0
AND tx.D != 0
AND tx.id IS NULL -- i.e. there isn't any