Sql query with fetch by condition - sql-server

Good day to you all. Faced with a problem and I am in a stupor, please help. You need to write an sql query according to the condition: where code = 2 and num = 2 then change the value, if code = 3 then take the record whose value code = 1
, a as (
select numberfn, street
from tbl
where code = 2
and nume = 2)
, b as (
select N from tbl where code = '3'
)
, actual as (
select b.value, a.N
from b
join a
on b.N = a.N
where b.code = '1'
union all
select st.value, st.N
from rreg st
join tbl b
on st.N = b.N
)
I tried to simplify it using case as well, but the second condition leads me to a dead end.
, actual as (
select N
, case when (code= 2 and num= 2)
then value
else .... (condition: select an entry for N where code = 1)
end value
from tbl
)

You have 2 requirements here, one is to update, the other is to select a value.
Separately they are:
UPDATE table
SET value = ??
WHERE code = 2 AND num = 2
And
SELECT * FROM table
WHERE code = 3 AND value = 1
(Where ?? = value you want to change the column value to.)
If you want both in one function, then they can be moved into a stored procedure.

Related

SQL Server : calculated column for parent/child level

Having some issues displaying a calculated column.
I'm displaying a line for parent, then a few (anywhere between 1-5) lines for each child item.
My first query is this:
Select
_r1 = pbhier.r1
, pb.parent_id
, pb.Product_id
, pb.LastCost
, pb.AverageCost
, pb.FirstDatePurchased
, lrd.LastReceivingDate
, inv_units = isnull(inv.quantity,0)
, sales_units = convert(int,isnull(sales.SalesUnits,0))
, number_months_supply = case when isnull(sales.salesUnits,0) = 0 then isnull(inv.quantity,0)
else
case when (isnull(sales.salesUnits,0)/12) = 0 then 0
else
(convert(int,(inv.quantity/(isnull(sales.salesUnits,0)/12)))) end end
, inv.quantity, sales.SalesUnits
, ext_AverageCost = isnull(inv.quantity,0) * pb.averagecost
INTO #tempdata
From Products pb
inner join #TempFinalHier pbhier on pb.product_id = pbhier.product_id
left join #inventoryPC inv (nolock) on pb.product_id = inv.product_id
left join #tempTotSalesPC sales (nolock) on pb.product_id = sales.product_id
left join #lastReceivingDate lrd on lrd.rm_product_id = pb.product_id
where pb.Parent_ID in (select parent_id from #FinalParentSelection)
This creates a temp data set. The column "number_months_supply" does not need to be calculated above but the same formula should be used in my final query. My final query below gets me the final result set:
Select distinct
H.R1 , H.R2, H.Lvl,
case
when R1 <> R2
then H.parent_sku
else H.SKU
end as SKU,
H.parent_sku,
FirstReceiptDate = min(B.FirstDatePurchased),
LastReceiptDate = max(B.LastReceivingDate),
OnHand = sum(B.inv_units),
SalesUnits = sum(B.sales_units),
case
when isnull(sum(B.sales_units),0) = 0
then isnull(sum(B.inv_units),0)
else
case
when (isnull(sum(B.sales_units),0)/12) = 0
then 0
else convert(decimal(10, 2), (sum(B.inv_units) / (isnull(sum(B.sales_units), 0) / 12)))
end
end,
max(B.ext_AverageCost) as ext_AverageCost
From
#TempFinalHier H
join
#TempData1 B on (B._R1 between H.R1 and H.R2)
-- where H.Lvl=1 --Show only parent line
Group By
H.R1, H.R2, H.Lvl, H.parent_sku
having
sum(B.number_months_supply) > 12 --#MonthsSupplyGreaterThanOrEqual
Order by
R1
What I'm trying to get is:
'onHand' for parent line (lvl1) needs to be sum of all child rows (lvl2). same applies to 'SalesUnits'. Finally, Number_months_supply formula is (inv/sales_units)*12. I would like to display the number_months_supply as numeric with 2 decimal points.
Would appreciate some help with this.
Thanks.

Recursive triggers and error : subquery returned more than 1 value

I need your help !
I am working on sql server
1-- I created this trigger but it seems to be wrong...
CREATE TRIGGER [dbo].[chargeAZero]
ON [dbo].[situations_final]
after INSERT
AS
BEGIN
SET nocount ON
UPDATE sfinal
SET charge = 00
FROM inserted i
INNER JOIN situations_final sfinal
ON i.referencepiece = sfinal.referencepiece
AND i.ancienposte = sfinal.ancienposte
AND i.numerophase = sfinal.numerophase
AND i.datestrategie = sfinal.datestrategie
/*and i.Datecadence=sfinal.Datecadence*/
WHERE (SELECT sfinal.nouveauposte
FROM situations_final sfinal
INNER JOIN inserted i
ON i.referencepiece = sfinal.referencepiece
AND i.ancienposte = sfinal.ancienposte
AND i.numerophase = sfinal.numerophase
AND i.datestrategie = sfinal.datestrategie) IS
NULL
END
The error message is always the same: the subquery returned more than one value... I think I wrote my trigger correctly as I did with others that work fine.
2-- My second question is : Is it possible to make only one trigger recursive ?
3-- As you have noticed on my database on the table "Nomenclatures" (Bill of materials in english) I have 3 elements:
*codepiecemere: The component mother
*codepiecefille: the component child
* the quantity.
I give you an example of what I need :
Mother= A Child= B Quantity= 2
Mother= B Child= C Quantity= 3
I want a trigger to give me a result like that:
A 1 B 2 C 6=2*3 (the quantity needed of C to make 1 B).
Thank you very much
Here's a recursive query that solves the material aggregation problem.
Table definition
CREATE TABLE [dbo].[Material](
[Mother] [varchar](100) NOT NULL,
[Child] [varchar](100) NOT NULL,
[Quantity] [int] NOT NULL,
)
and the query:
WITH Result(mother, child, quantity)
AS
(
select * from material
union all
select M.mother, R.Child, M.quantity * R.Quantity as Quantity
from Result R INNER JOIN Material M ON M.Child = R.Mother
)
select * from result
You can see an example here: http://sqlfiddle.com/#!6/6dc64/1
UPDATE:
Sql fiddle is not working, I don't know why
UPDATE 2
Sql Fiddle is back! :-)
The is null is not normally used with subqueries. Try this:
where not exists (select 1
from SITUATIONS_Final sfinal inner join inserted i
on i.ReferencePiece=sfinal.ReferencePiece
and i.AncienPoste=sfinal.AncienPoste
and i.numerophase=sfinal.numerophase
and i.datestrategie=sfinal.datestrategie
)
This is assuming that the is null is testing for no values being returned, as opposed to a NULL value in sfinal.nouveauposte. If the latter:
where exists (select 1
from SITUATIONS_Final sfinal inner join inserted i
on i.ReferencePiece=sfinal.ReferencePiece
and i.AncienPoste=sfinal.AncienPoste
and i.numerophase=sfinal.numerophase
and i.datestrategie=sfinal.datestrategie
where sfinal.nouveauposte is null
)
EDIT:
Do you need the subquery at all?
UPDATE sfinal
SET charge = 00
FROM inserted i
INNER JOIN situations_final sfinal
ON i.referencepiece = sfinal.referencepiece
AND i.ancienposte = sfinal.ancienposte
AND i.numerophase = sfinal.numerophase
AND i.datestrategie = sfinal.datestrategie
WHERE sfinal.nouveauposte IS NULL;
I think the problem is that you are inserting more than one row in a single command, so the inserted table contains more than one row. As a consequence the sub query
SELECT sfinal.nouveauposte
FROM situations_final sfinal
INNER JOIN inserted i
ON i.referencepiece = sfinal.referencepiece
AND i.ancienposte = sfinal.ancienposte
AND i.numerophase = sfinal.numerophase
AND i.datestrategie = sfinal.datestrategie
contains more than one row too and cannot be compared to NULL that is a scalar value.
I am ambitious :D I tried to improve the script:
WITH RESULT (MOTHER, CHILD, QUANTITY)
as
(
select Mother, Child, CONVERT(Numeric(10,0), Quantity) as Quantity from bilangammestest
union all select M.mother, R.Child, CONVERT(Numeric(10,0), M.quantity * R.Quantity) as Quantity from Result R
INNER JOIN bilangammestest M ON M.Child = R.Mother
)
select * from result
where mother not in (select child from bilangammestest )
Here are the data I have on my table "Bilangammestest":
Z A 1
Z Y 1
A B 2
Y B 2
B C 3
Here are the result I get :
Z A 1
Z Y 1
Z C 6
Z C 6
Z B 2
Z B 2
Here is the Final result I want:
Z A 1
Z Y 1
Z C 12
Z B 4
I tried to do a 'sum' but I couldn't do it correctly :(

How case in SELECT clause can affect the resultset in SQL Server?

I'm facing a strange behavior in SQL Server. I have a query how return 233 rows and it's fine.
The problem is if I add a condition in a CASE, well, she returns 48 rows. How is it possible ? CASE shouldn't change my results : it's a CASE in a SELECT clause and there is no WHERE on it.
See the query below. The part between * ... * is the condition who change the result of the entire query.
SELECT * FROM (
SELECT
CASE
WHEN dq.type_of_cover = 'ndd' AND ah.type_of_cover = 'ndaa' THEN ah.type_of_cover
ELSE dq.type_of_cover
END AS type_of_cover,
CASE
WHEN (dq.type_of_cover = 'CCD' AND dq.result_code = 'CCP') THEN NULL --a.mntgex
WHEN (ah.type_of_cover = 'ndaa' *** AND ah.date = GETDATE() ***) THEN ah.first_amount
ELSE ISNULL(dq.first_amount, 0)
END AS problem,
dq.active
FROM (
SELECT du.coddeb, du.coduti
FROM cacheDebiteurConsolideByUtilisateur AS du
WHERE du.coduti = 4102
) AS debi
INNER JOIN DecisionQueue AS dq ON dq.coddeb = debi.coddeb
OUTER APPLY (
SELECT TOP 1 type_of_cover, MIN(date) AS date, first_amount, coddeb, codadh
FROM AtradiusCLHistory
WHERE codadh = 1003
AND dq.coddeb = coddeb
GROUP BY type_of_cover, first_amount, coddeb, codadh
) AS ah
WHERE dq.codadh = 1003
AND dq.cancelled != 1
) AS test
WHERE type_of_cover = 'ndaa' AND active = 1
So when I got AND ah.date = GETDATE() in the "problem" CASE, I have 48rows, when not, 233.

TSQL while loop

UPDATE Houses
SET lStatus = U.codesum
FROM Houses H
JOIN (SELECT ref, SUM(code) AS codesum
FROM Users
GROUP BY ref) AS U ON U.ref = H.ref
The above code gets all users for every house (Houses table). SUMs the code column (Users table) for all users. And finally updates the result in lstatus column of the houses table.
My question is:
I need to rewrite the query which is NOT to sum the code column. Rather I want to create case statements. for example:
tempvar = 0 //local variable might be required
For each user {
If code == 1 then tempvar += 5
else if code == 2 then tempvar += 10
etc
tempvar = 0;
}
Once we have looped through all the users for each house we can now set lStatus = tempvar.
The tempvar should then be reset to 0 for the next house.
You should try to avoid loops and other procedural constructs when coding SQL. A relational database can't easily optimize such things and they often perform orders of magnitude slower than their declarative counterparts. In this case, it seems simple enough to replace your SUM(code) with the CASE statement that you describe:
UPDATE Houses
SET lStatus = U.codesum
FROM Houses H
JOIN (SELECT ref, SUM(CASE code WHEN 1 THEN 5 WHEN 2 THEN 10 ELSE 0 END) AS codesum
FROM Users
GROUP BY ref) AS U ON U.ref = H.ref
In this way, SUM can still handle the duty that you imagine your temp variable would be doing.
Also, if you have many cases, you might think about putting those in a table and simply joining on that to get your sum. This might be better to maintain. I'm using a table variable here, but it could look like the following:
DECLARE #codes TABLE (
code INT NOT NULL PRIMARY KEY,
value INT NOT NULL
)
INSERT INTO #codes SELECT 1, 5
INSERT INTO #codes SELECT 2, 10
UPDATE Houses
SET lStatus = U.codesum
FROM Houses H
JOIN (SELECT a.ref, SUM(b.value) AS codesum
FROM Users a
JOIN #codes b on a.code = b.code -- Here we get the values dynamically
GROUP BY a.ref) AS U ON U.ref = H.ref
Try this:
UPDATE Houses
SET lStatus = U.codesum
FROM Houses H
JOIN (
SELECT ref, SUM(
CASE
WHEN Code = 1
THEN 5
WHEN Code = 2
THEN 10
END
) AS codesum
FROM Users
GROUP BY ref
) AS U ON U.ref = H.ref
Try this :
UPDATE Houses
SET lStatus = U.code
FROM Houses H
JOIN (
SELECT ref, SUM(
CASE
WHEN Code = 1
THEN 5
WHEN Code = 2
THEN 10
ELSE 0
END
) AS code
FROM Users
GROUP BY ref
) AS U ON U.ref = H.ref

SQL query - need to exclude if Requirement NOT met, and exclude if Disqualifier IS met

I have a feeling once i see the solution i'll slap my forehead, but right now I'm not seeing it.
I have a lookup table, say TableB, which looks like this. All fields are INT except the last two which are BOOL.
ID, TableA_ID, Value, Required, Disqualifies
I have a list of TableA_Id values (1, 2, 3 ) etc
For each record in this table, either Required can be true or disqualified can be true - they cant both be true at the same time. They can both be false or null though. There can be duplicate values of TableA_Id but there should never be duplicates of TableA_Id and Value
If required is true for any of those TableA_ID values, and none of those values are in my list, return no records. If none of the values are marked as required (required = 0 or null) then return records UNLESS any of the values are marked as Disqualifies and are in the list, in which case i want to return no records.
So - if a field is required and i dont have it, dont return any records. If a field is marked as disqualified and i have it, don't return any records. Only return a record if either i have a required value or don't have a disqualified value or there are no required values.
I hope I explained myself clearly.
Thanks in advance for pointing me in the right direction.
As an example of what my records might look like:
ID TableA_ID Value Required Disqualifies
-- --------- ----- -------- ------------
1 123 1 True False
2 123 2 True False
3 123 3 False False
4 123 4 False True
5 456 1 False True
6 456 2 False False
Given this set of sample data, if we're working with TableA_Id 123 and my list of values is lets say 1 and 3, i would get data returned because i have a required value and dont have any disqualified values. If my list of values were just 3, i'd get no records since i'm missing of the Required values. If my list of values were 1 and 4, i'd get no records because 4 is marked as disqualified.
Now if we're working with TableA_Id 456, the only list of values that would return any records is 2.
Maybe i should post the whole SQL query - i was trying to keep this short to make it easier for everyone, but it looks like maybe that's not working so well.
Here is the full dynamically generated query. The bit i am working on now is the 2nd line from the bottom. To equate this to my example, t.id would be TableA_ID, Value would be PDT_ID.
SELECT DISTINCT t.ID, t.BriefTitle, stat.Status, lstat.Status AS LocationStatus, st.SType, t.LAgency, l.City, state.StateCode
,( SELECT TOP 1 UserID
FROM TRecruiter
WHERE TrialID = t.ID AND Lead = 1 ), l.ID as LocationID
, l.WebBased
FROM Trial t
INNER JOIN Location l ON t.ID = l.TrialID
FULL JOIN pdt on t.ID = pdt.trialid
FULL JOIN pdm on t.ID = pdm.TrialID
FULL JOIN s on t.ID = s.TrialID
FULL JOIN hy on t.ID = hy.TrialID
FULL JOIN ta on t.ID = ta.TrialID
FULL JOIN stt on t.ID = stt.TrialID
FULL JOIN [Status] stat ON t.StatusID = stat.ID
FULL JOIN st ON t.StudyTypeID = st.ID
FULL JOIN State state ON l.StateID = state.ID
FULL JOIN [Status] lstat ON l.StatusID = lstat.ID
FULL JOIN ts ON t.ID = ts.TrialID
FULL JOIN tpdm ON t.ID = tpdm.TrialID
WHERE ((t.ID IS NOT NULL)
AND (EligibleHealthyVolunteers IS NULL OR EligibleHealthyVolunteers = 1 OR (0 = 0 AND EligibleHealthyVolunteers = 0))
AND (eligiblegenderid is null OR eligiblegenderid = 1 OR eligiblegenderid = 3)
AND ((EligibleMinAge <= 28 AND EligibleMaxAge >= 28) OR (EligibleMinAge <= 28 AND EligibleMaxAge is null) OR (EligibleMinAge IS NULL AND EligibleMaxAge >= 28))
AND (HYID = 6 AND (hy.Disqualify = 0 OR hy.Disqualify IS NULL AND NOT EXISTS (SELECT * FROM hy WHERE t.id = hy.TrialID AND hy.Req =1)) OR HYID = 6 AND hy.req = 1)
AND (PDT_ID IN (1) AND ( pdt.Disqualify = 0 OR pdt.Disqualify IS NULL AND NOT EXISTS (select * from pdt where t.id = pdt.TrialID AND pdt.Req = 1)) OR PDT_ID IN (1) AND (pdt.Req = 1 AND (pdt.Disqualify = 0 or pdt.Disqualify is null )))
) AND ((3959 * acos(cos(radians(34.18)) * cos(radians(l.Latitude)) * cos(radians(l.Longitude) - radians(-118.46)) + sin(radians(34.18)) * sin(radians(l.Latitude)))) <= 300 OR l.Latitude IS NULL) AND t.IsPublished = 1 AND (t.StatusID = 1 OR t.StatusID = 2)
I've changed/shortened some table names just for security/privacy reasons.
Edit:
I think i am close to getting this working, but I'm getting tripped up on the logic again.
I have the following bit of sql:
AND ( exists (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id AND pdT_ID IN (2) ) AND EXISTS (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id ) )
I'm not sure how to structure this. Those two exists statement should make the whole thing true in the following combination:
True & False
True & True
False & False
If it's False & True, then the whole thing is false. In other words if there is a Req =1 AND the PDT_ID that is marked as Req=1 is not in our list (in the example above the list just contains '2') then return false.
EDIT:
I think i finally got it.
AND NOT EXISTS (SELECT * FROM pdt WHERE Disqualify = 1 AND trialid = t.id AND PDT_ID IN (2) )
AND NOT ( NOT exists (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id AND PDT_ID IN (2) ) AND EXISTS (SELECT * FROM pdt WHERE Req = 1 AND trialid = t.id ) )
So far this seems to work in testing. Although I'm only working with two values of PDT_ID. If this does resolve my problem, i will come back and give someone the credit for helping me.
SELECT *
FROM TABLEB B
WHERE
(
B.REQUIRED = 1
AND EXISTS
(
SELECT 1
FROM TABLEA A
WHERE A.ID =B.TABLEA_ID
)
)
OR
(
B.REQUIRED != 1
AND B.DISQUALIFIES <> 1
)
OR
(
B.REQUIRED != 1
AND B.DISQUALIFIES = 1
AND EXISTS
(
SELECT 1
FROM TABLEA A
WHERE A.ID =B.TABLEA_ID
)
)
UPDATE - after the EDIT and explanation from OP:
Change the line
FULL JOIN pdt on t.ID = pdt.trialid
To
FULL JOIN (SELECT * FROM pdt BB WHERE
BB.TrialID IN (SELECT AA.ID FROM Trial AA WHERE AA.ID = BB.TrialID) AND
1 > (SELECT COUNT(*) FROM Trial A
LEFT OUTER JOIN pdt B ON B.Req != 1 AND B.Disqualify != 1 AND B.TrialID = A.ID
WHERE B.TrialID IS NULL)) pdt ON t.ID = pdt.TiralID
AND change the line before last from
AND (PDT_ID IN (1) AND ( pdt.Disqualify = 0 OR pdt.Disqualify IS NULL AND NOT EXISTS (select * from pdt where t.id = pdt.TrialID AND pdt.Req = 1)) OR PDT_ID IN (1) AND (pdt.Req = 1 AND (pdt.Disqualify = 0 or pdt.Disqualify is null )))
To
AND PDT_ID IN (1)
(You seem to have found a solution, yet I've decided to share my thoughts about this problem anyway.)
Given you've got a set of TableA IDs, each of which is accompanied by a set of some values, and you want to test the entire row set against this TableB thing using the rules you've set forth, I think the entire checking process might look like this:
Match every pair of TableA.ID and Value against TableB and get aggregate maximums of Required and Disqualifies for every TableA.ID along the way.
Derive a separate list of TableA_ID values with their corresponding maximum values of Required, from TableB. That will be for us to know whether a particular TableA_ID must have a required value at all.
Match the row set obtained at Stage 1 against the derived table (Stage 2) and check the aggregate values:
1) if the actual aggregate Disqualifies for a TableA_ID is 1, discard this TableA_ID set;
2) if a TableA_ID has a match in the Stage 2 derived table and the aggregate maximum of Required that we obtained at Stage 1 doesn't match the maximum Required in the derived table, discard the set as well.
Something tells me that it would be better at this point to move on to some sort of illustration. Here's a sample script, with comments explaining which part of the script implements which part of the description above:
;
WITH
/* this is the row set to be tested and which
is supposed to contain TableA.IDs and Values */
testedRowSet AS (
SELECT
TableA.ID AS TableA_ID,
SomethingElse.TestedValue AS Value,
...
FROM TableA
JOIN SomethingElse ON some_condition
...
),
/* at this point, we are getting the aggregate maximums
of TableB.Required and TableB.Disqualifies for every
TableA_ID in testedRowSet */
aggregated AS (
SELECT
testedRowSet.TableA_ID,
testedRowSet.Value,
...
DoesHaveRequiredValues = MAX(CASE TableB.Required WHEN 1 THEN 1 ELSE 0 END) OVER (PARTITION BY testedRowSet.TableA_ID),
HasDisqualifyingValues = MAX(CASE TableB.Disqualifies WHEN 1 THEN 1 ELSE 0 END) OVER (PARTITION BY testedRowSet.TableA_ID)
FROM testedRowSet
LEFT JOIN TableB ON testedRowSet.TableA_ID = TableB.TableA_ID
AND testedRowSet.Value = TableB.Value
),
/* this row set will let us see whether a particular
TableA_ID must have a required value */
properties AS (
SELECT
TableA_ID,
MustHaveRequiredValues = MAX(CASE Required WHEN 1 THEN 1 ELSE 0 END)
FROM TableB
GROUP BY TableA_ID
),
/* this is where we are actually checking the previously
obtained aggregate values of Required and Disqualifies */
tested AS (
SELECT
aggregated.TableA_ID,
aggregated.Value,
...
FROM aggregated
LEFT JOIN properties ON aggregated.TableA_ID = properties.TableA_ID
WHERE aggregated.HasDisqualifyingValues = 0
AND (properties.TableA_ID IS NULL
OR properties.MustHaveRequiredValues = aggregated.DoesHaveRequiredValues)
)
SELECT * FROM tested

Resources