Dynamic column value with group by (sql server and Linq) - sql-server

i have a table Plan with following sample data
i want to aggregate the result by PlanMonth and for PlanStatus i want that if any of its (in a group) values is Drafted i get drafted in the result and Under Approval otherwise. i have done it using following query
select PlanMonth, case when Flag=1 then 'Drafted' else 'Under Approval' end as PlanStatus
from
(select p.PlanMonth, Max(CASE WHEN p.PlanStatus = 'Drafted' THEN 1 ELSE 0 END) Flag
from Plans p
group by p.PlanMonth
) inquery
i have consulted this blog post. Is there something wrong with it? Moreover, if someone can help me translate it to linq i will be grateful

The query you have will work.
With the sample data you have provided it can be simplified a bit.
select p.PlanMonth,
min(p.PlanStatus) as PlanStatus
from Plans as p
group by p.PlanMonth
This will not work if you have values in PlanStatus that is alphabetically sorted before Drafted.

Following Linq query worked for me
return (from p in db.mktDrVisitPlans
group p by p.PlanMonth into grop
select
new VMVisitPlan
{
PlanMonth = grop.Key
PlanStatus = grop.Any(x=>x.p.PlanStatus == "Drafted")?"Hold":"Under Approval",
}).ToList();

Related

sum(case When.. AND) with multiple conditions not working

I am trying to run this sum query to produce two columns of Turnover one for TY and another for LY. However, I want any transactions flagged as Cancelled to appear as negatives:
select [Location],BR.BranchName,
sum(case when (FX.TransactionDateKey between '20171101' and '20181031')
and ([Action] = 'Cancelled')
then FX.CustomerValue*-1 else [CustomerValue] end) as [CustmVal TY],
sum(case when (FX.TransactionDateKey between '20161101' and '20171031')
and ([Action] = 'Cancelled')
then FX.CustomerValue*-1 else FX.CustomerValue*1 end) AS [CustmVal LY]
from [dbo].[FRX_Transactions] FX
inner join DWX_Branch BR on BR.BranchID=FX.[Location]
where FX.TransactionDateKey between '20161101' and '20181031' and BR.BusinessDivision = 'Retail'
and FX.[Action] in ('Trade','cancelled') and FX.Reason in ('Public','BBG','Overridesupplyrate') and FX.Operation in ('Add','Del')
group by FX.[Location],BR.BranchName, BR.BranchOpenDate,BR.BranchCloseDate,BR.ActiveStatus
order by BR.BranchName
However, when I run it I get similar data in both columns - it seems to ignore the date conditions.
Please, what am I doing wrong? Is this case-when-statement with TWO conditions written wrong?
Any help would be HUGELY appreciated. Massive thanks!
I think what you actually want for your CASE expression is:
CASE WHEN FX.TransactionDateKey BETWEEN '20171101' AND '20181031' THEN [CustomerValue] *
CASE WHEN [Action] = 'Cancelled' THEN -1 ELSE 1 END
END

Missing data row in NOT IN clause

I just realised that my Auto-Price Calculation doesn't fill the Prices for ListID 4.
I inserted the Prices from the SELECT shown below.
For bugg research I executed the SELECT without the WHERE part and it shows me the example data row.
I can't find the error though, why it is not shown in the complete select (it has no entry with ListID = 4).
Someone can see my mistake?
Edit: Just tried the subselect alone, it shows no rows for the requested article. Why is the NOT IN clause unaffected by this fact?
Most likely, it's because of how you are combining the artikelnummer and the auspraegungID.
I do not think you have accounted for that fact that '100' + '0' is idential to '10' + '00'.
Instead of trying to merge two fields into one, perhaps try the following?
SELECT
*
FROM
#allArticles AS allArticles
WHERE
Artikelnummer = 'IT-810260'
AND NOT EXISTS (SELECT *
FROM KHKPreisListenArtikel
WHERE ListeID = 4
AND Artikelnummer = allArticles.Artikelnummer
AND Auspraegung = allArticles.Auspraegung
)
If that still doesn't work, then you must have corresponding records in that other table, find them like this...
SELECT
*
FROM
#allArticles AS allArticles
INNER JOIN
KHKPreisListenArtikel AS Preis
ON Preis.ListeID = 4
AND Preis.Artikelnummer = allArticles.Artikelnummer
AND Preis.Auspraegung = allArticles.Auspraegung
WHERe
allArticles.Artikelnummer = 'IT-810260'
PLEASE ALSO NOTE
Please don't include images of code, please copy the code, so that we can copy it too.
Especially when the tables/fields are in another language...
EDIT
Here is a query that will show the cause of your original query to fail.
SELECT
*
FROM
#allArticles AS allArticles
INNER JOIN
KHKPreisListenArtikel AS Preis
ON Preis.ListeID = 4
AND Preis.Artikelnummer + CONVERT(VARCHAR(50), Preis.Auspraegung)
=
allArticles.Artikelnummer + CONVERT(VARCHAR(50), allArticles.Auspraegung)
WHERE
allArticles.Artikelnummer = 'IT-810260'

case statement filter in MDX query

I want to write the following T SQL query in MDX
Select count(bugs),priority from table
where
Case when priority =1 then startdate< dateadd(dd,-7,getdate())
when priority =2 then startdate< dateadd(dd,-14,getdate())
end
group by priority
Tried the following but not working
WITH MEMBER [Measures].CHECKING
AS
CASE [Item].[ startdate].CurrentMember
WHEN [Item].[ Priority].&[1] THEN [Item].[startdate]<DATEADD(DAY,-7,NOW())
WHEN [Item].[ Priority].&[2] THEN [Item].[startdate]<DATEADD(DAY,-14,NOW())
END
SELECT
NON EMPTY{[Measures].[Count], [Measures].CHECKING }ON COLUMNS
,NON EMPTY{([Item].[ Priority].[ Priority].ALLMEMBERS )}
I am new to MDX queries, any suggestions on how to approach this please..
Your CASE logic has a basic problem. The statement cannot result in a condition. It can only result in a value that you then compare to something else.
To take your tSQL example, I think it should read more like this:
Select count(bugs),priority from table
where
1 = Case when priority = 1 and startdate< dateadd(dd,-7,getdate()) Then 1
when priority = 2 and startdate< dateadd(dd,-14,getdate()) then 1
else 0 end
group by priority
A cleaner way to write this would be to skip the CASE altogether.
Select count(bugs),priority from table
where
(priority = 1 and startdate< dateadd(dd,-7,getdate()))
or
(priority = 2 and startdate< dateadd(dd,-14,getdate()))
group by priority
I am assuming the following:
Your startdate hierarchy is an attribute hierarchy, not a user hierarchy and
the current day is its last member.
Then the following MDX should deliver what you want:
SELECT
{ [Measures].[Count] }
ON COLUMNS
,
{ [Item].[ Priority].&[1], [Item].[ Priority].&[2] }
ON ROWS
FROM (
SELECT ({ [Item].[ Priority].&[1] }
*
([Item].[ startdate].[ startdate].Members
- Tail([Item].[ startdate].[ startdate].Members, 7)
)
)
+
({ [Item].[ Priority].&[2] }
*
([Item].[ startdate].[ startdate].Members
- Tail([Item].[ startdate].[ startdate].Members, 14)
)
)
ON COLUMNS
FROM [yourCube]
)
Your code [Item].[startdate]<DATEADD(DAY,-7,NOW()) does not work in MDX for several reasons: firstly, [Item].[startdate] is a hierarchy, and hence cannot be compared using <. Secondly, even if you would re-state it as [Item].[startdate].CurrentMember < DATEADD(DAY,-7,NOW()), you would have a member on the left side of the <, and a date , i. e. a value, on the right side. One of the important things to keep in mind with MDX are the different types of objects: Hierarchies, levels, members, tuples, sets. And all these are not values. You do not just have columns like in SQL.

Yet another subquery issue

Hello from an absolute beginner in SQL!
I have a field I want to populate based on another table. For this I have written this query, which fails with: Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The statement has been terminated.
oK, here goes:
Update kre.CustomerOrderLineCopy
SET DepNo = (SELECT customerordercopy.DepNo
FROM kre.CustomerOrderCopy , kre.CustomerOrderLineCopy
WHERE CustomerOrderLineCopy.OrderCopyNo =kre.CustomerOrderCopy.OrderCopyNo)
WHERE CustomerOrderLineCopy.OrderCopyNo = (SELECT CustomerOrderCopy.OrderCopyNo
FROM kre.CustomerOrderCopy, kre.CustomerOrderLineCopy
WHERE kre.CustomerOrderLineCopy.OrderCopyNo = kre.CustomerOrderCopy.OrderCopyNo)
What I'm trying to do is to change DepNo in CustomerOrderLineCopy, with the value in DepNo in CustomerOrderCopy - based on the same OrderCopyNo in both tables.
I'm open for all suggestion.
Thanks,
ohalvors
If you just join the tables together the update is easier:
UPDATE A SET A.DepNo = B.DepNo
FROM kre.CustomerOrderLineCopy A
INNER JOIN kre.CustomerOrderCopy B ON A.OrderCopyNo = B.OrderCopyNo
The problem is that at least one of your sub queries return more than one value. Think about this:
tablePerson(name, age)
Adam, 11
Eva, 11
Sven 22
update tablePerson
set name = (select name from tablePerson where age = 11)
where name = 'Sven'
Which is equivalent to: set Sven's name to Adam and Eva. Which is not possible.
If you want to use sub queries, either make sure your sub queries can only return one value or force one value by using:
select top 1 xxx from ...
This may be enough to quieten it down:
Update kre.CustomerOrderLineCopy
SET DepNo = (SELECT customerordercopy.DepNo
FROM kre.CustomerOrderCopy --, kre.CustomerOrderLineCopy
WHERE CustomerOrderLineCopy.OrderCopyNo =kre.CustomerOrderCopy.OrderCopyNo)
WHERE CustomerOrderLineCopy.OrderCopyNo = (SELECT CustomerOrderCopy.OrderCopyNo
FROM kre.CustomerOrderCopy --, kre.CustomerOrderLineCopy
WHERE kre.CustomerOrderLineCopy.OrderCopyNo = kre.CustomerOrderCopy.OrderCopyNo)
(Where I've commented out kre.CustomerOrderLineCopy in the subqueries) That is, you were hopefully trying to correlate these subqueries with the outer table - not introduce another instance of kre.CustomerOrderLineCopy.
If you still get an error, then you still have multiple rows in kre.CustomerOrderCopy which have the same OrderCopyNo. If that's so, you need to give us (and SQL Server) the rules that you want to apply for how to select which row you want to use.
The danger of switching to the FROM ... JOIN form shown in #Avitus's answer is that it will no longer report if there are multiple matching rows - it will just silently pick one of them - which one is never made clear.
Now I look at the query again, I'm not sure it even needs a WHERE clause now. I think this is the same:
Update kre.CustomerOrderLineCopy
SET DepNo = (
SELECT customerordercopy.DepNo
FROM kre.CustomerOrderCopy
WHERE CustomerOrderLineCopy.OrderCopyNo = kre.CustomerOrderCopy.OrderCopyNo)

Need to use information from one qry to dictate an action on another

Ok so this is going to sound a little complicated. I want to somehow put some kind of function that will divide a table value by two when its Policy number matches up with a policy number in another table.
Here is the query where I want that functions
SELECT
qryReinsuranceDPA1_izzy.POLICY_NO,
qryReinsuranceDPA1_izzy.PHASE_CODE,
qryReinsuranceDPA1_izzy.SUB_PHASE_CODE,
qryReinsuranceDPA1_izzy.SchedNP,
qryReinsuranceDPA1_izzy.ProdType,
Sum(qryReinsuranceDPA1_izzy.SumOfAMOUNT_INFORCE) AS SumOfSumOfAMOUNT_INFORCE,
Sum(qryReinsuranceDPA1_izzy.SumOfPUA_FACE) AS SumOfSumOfPUA_FACE,
Sum(qryReinsuranceDPA1_izzy.SumOfOYT_FACE) AS SumOfSumOfOYT_FACE, TotalDPA = sum(case when qryReinsuranceDPA1_izzy.[SumOfNetDefExtraAdj] Is Null then qryReinsuranceDPA1_izzy.[SumOfNetDefPremiumAdj] else qryReinsuranceDPA1_izzy.[SumOfNetDefPremiumAdj] +qryReinsuranceDPA1_izzy.[SumOfNetDefExtraAdj] end),
qryReinsuranceDPA1_izzy.SumOfGROSS_ANNLZD_PREM,
qryReinsuranceDPA1_izzy.SumOfStatNetPremium,
qryReinsuranceDPA1_izzy.[SumOfStatNetPremium]/qryReinsuranceDPA1_izzy.[SumOfGROSS_ANNLZD_PREM] AS NetToGrossRatio,
qryReinsuranceDPA1_izzy.NetvsGrossInd,
DPA_NetPrem = case when qryReinsuranceDPA1_izzy.[NetvsGrossInd]='Net' then sum(qryReinsuranceDPA1_izzy.[SumOfStatNetPremium]) else sum([qryReinsuranceDPA1_izzy].[SumOfGROSS_ANNLZD_PREM]) end,
qryPolicyListforNYDefPRemAsset_Re.ReinType AS ReinType,
Sum(qryPolicyListforNYDefPRemAsset_Re.ReinsAmount) AS SumOfReinsAmount,
qryPolicyListforNYDefPRemAsset_Re.[ReinsAmount]/(qryReinsuranceDPA1_izzy.[SumOfAMOUNT_INFORCE]+qryReinsuranceDPA1_izzy.[SumOfOYT_FACE]+qryReinsuranceDPA1_izzy.[SumOfPUA_FACE]) AS [Reins%],
qryPolicyListforNYDefPRemAsset_Re.ReinsStatRsv AS ReinsStatRsv,
Sum(qryPolicyListforNYDefPRemAsset_Re.SumOfGROSS_ANNLZD_PREM) AS ReinsPrem, qryReinsuranceDPA1_izzy.PAID_TO_DATE,
qryReinsuranceDPA1_izzy.VAL_DATE,
qryReinsuranceDPA1_izzy.ISSUE_DATE
FROM qryPolicyListforNYDefPRemAsset_Re RIGHT JOIN
qryReinsuranceDPA1_izzy
ON
qryReinsuranceDPA1_izzy.POLICY_NO = qryPolicyListforNYDefPRemAsset_Re.POLICY_NO
AND qryReinsuranceDPA1_izzy.PHASE_CODE = qryPolicyListforNYDefPRemAsset_Re.PHASE_CODE AND
qryReinsuranceDPA1_izzy.SUB_PHASE_CODE= qryPolicyListforNYDefPRemAsset_Re.SUB_PHASE_CODE
GROUP BY
qryReinsuranceDPA1_izzy.POLICY_NO,
qryReinsuranceDPA1_izzy.PHASE_CODE,
qryReinsuranceDPA1_izzy.SUB_PHASE_CODE,
qryReinsuranceDPA1_izzy.SchedNP,
qryReinsuranceDPA1_izzy.ProdType,
qryReinsuranceDPA1_izzy.SumOfGROSS_ANNLZD_PREM,
qryReinsuranceDPA1_izzy.SumOfStatNetPremium,
qryReinsuranceDPA1_izzy.[SumOfStatNetPremium]/qryReinsuranceDPA1_izzy.[SumOfGROSS_ANNLZD_PREM],
qryReinsuranceDPA1_izzy.NetvsGrossInd,
qryPolicyListforNYDefPRemAsset_Re.ReinType,
qryPolicyListforNYDefPRemAsset_Re.[ReinsAmount]/(qryReinsuranceDPA1_izzy.[SumOfAMOUNT_INFORCE]+qryReinsuranceDPA1_izzy.[SumOfOYT_FACE]+qryReinsuranceDPA1_izzy.[SumOfPUA_FACE]),
qryPolicyListforNYDefPRemAsset_Re.ReinsStatRsv,
qryReinsuranceDPA1_izzy.PAID_TO_DATE,
qryReinsuranceDPA1_izzy.VAL_DATE,
qryReinsuranceDPA1_izzy.ISSUE_DATE
GO
and this is the qry that contains the policy numbers that I want divided by 2 in the above qry.
SELECT
qryReinsuranceDPA1.POLICY_NO,
qryReinsuranceDPA1.PHASE_CODE,
qryReinsuranceDPA1.SUB_PHASE_CODE,
qryReinsuranceDPA1.ProdType,
TotalDPA = Sum(case when [SumOfNetDefExtraAdj] Is Null then [SumOfNetDefPremiumAdj] else [SumOfNetDefPremiumAdj] + SumOfNetDefExtraAdj end),
Sum(1) AS Expr1
FROM qryPolicyListforNYDefPRemAsset_Re RIGHT JOIN qryReinsuranceDPA1
ON
qryReinsuranceDPA1.POLICY_NO = qryPolicyListforNYDefPRemAsset_Re.POLICY_NO AND
qryReinsuranceDPA1.PHASE_CODE= qryPolicyListforNYDefPRemAsset_Re.PHASE_CODE AND
qryReinsuranceDPA1.SUB_PHASE_CODE = qryPolicyListforNYDefPRemAsset_Re.SUB_PHASE_CODE
GROUP BY qryReinsuranceDPA1.POLICY_NO,
qryReinsuranceDPA1.PHASE_CODE,
qryReinsuranceDPA1.SUB_PHASE_CODE,
qryReinsuranceDPA1.ProdType
HAVING (((Sum(1))<>1))
GO
quick example. Say that the Policy number 064543200 is located in the results of that second qry. I then want the number located in first qry in Total DPA assosciated with that Policy number to be divided by 2.
If this is still confusing please let me know and I will try to explain better. Both are views.

Resources