Pivot table how to not allow nulls in multiple columns - sql

I want to put a condition if [2015] and [2016] are NULL then hide row,
but I cant pull it off.
I don't have interest in the billname if it doesn't have data.
SELECT
IssuedByUserGroup,
BILLNAME,
SUM([2016]) AS [2016],
SUM([2015])AS [2015]
FROM Sum_Orders
PIVOT
(
SUM(Sum_SellPrice)
FOR OrderperiodYear IN ([2016],[2015])
) AS pvt
WHERE ( (MONTH(OrderDate) = MONTH(GETDATE())
AND day(OrderDate) <= DAY(GETDATE())) OR MONTH(OrderDate) < MONTH(GETDATE()))
--This part above is just for getting the data since january 1 to sep 23(to the date)
AND OrderStatus in ('Complete','invoiced')
AND OrderPrefix IN ('LAX6')
GROUP BY BILLNAME,IssuedByUserGroup
ORDER BY IssuedByUserGroup desc
This is returning the following as expected:
Thank you !

Add COALESCE under GROUP BY part:
HAVING COALESCE(SUM([2016]), SUM([2015])) IS NOT NULL

You should be able to use a WHERE clause below the PIVOT, something like this:
WHERE [2015] IS NOT NULL

Related

Using Window Functions With Comparison Operator

I have the following query within a cte.
SELECT [item_id]
FROM [AWS_Stage]
WHERE [yr] IN('2020')
GROUP BY [item_id]
HAVING SUM(ISNULL([frcst_qty], 0)) >= 0
In the past I just needed all item_id's in 2020 greater than 0.
I now need to have all item id's greater than 0 by customer groupings. A line of code like the following makes sense:
SUM([frcst_qty]) OVER (PARTITION BY [item_id], [keycust4]) >= 0
I can't use a window function in a HAVING clause, and I can't have a comparison operator in the SELECT statement.
Any advice on how to make this work?
Could you please try using a subquery like below? This calculated the sum using window function and then using filter on the result. I removed year condition.
SELECT
[item_id]
FROM
(
SELECT
[item_id],
SUM([frcst_qty]) OVER (PARTITION BY [item_id], [keycust4] ORDER BY [item_id], [keycust4]) sum_qty
FROM
[AWS_Stage] ) subq
WHERE
sum_qty >=0
GROUP BY
[item_id]
select [keycust4], [item_id]
from [aws_stage]
where [yr] = '2020'
group by [keycust4], [item_id]
having SUM(ISNULL([frcst_qty], 0)) >= 0
try this. not sure though if i understood your question correctly

SQL with as expression shows multiple results

I am writing a SQL query using with as expression. I always get a result in the square of what I required.
This is my query:
DECLARE #MAX_DATE AS INT
SET #MAX_DATE = (SELECT DATEPART(MONTH,FECHA) FROM ALBVENTACAB WHERE NUMALBARAN IN (SELECT DISTINCT MAX(NUMALBARAN) FROM ALBVENTACAB));
;WITH TABLE_LAST AS (
SELECT CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA)) as LAST_YEAR_MONTH
,SUM(TOTALNETO) AS LAST_YEAR_VALUE
FROM ALBVENTACAB
WHERE DATEPART(YEAR,CURRENT_TIMESTAMP) -1 = DATEPART(YEAR,FECHA) AND NUMSERIE LIKE 'A%'
AND DATEPART(MONTH,FECHA) <= #MAX_DATE
GROUP BY CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA))
)
,TABLE_CURRENT AS(
SELECT CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA)) as CURR_YEAR_MONTH
,SUM(TOTALNETO) AS CURR_YEAR_VALUE
FROM ALBVENTACAB
WHERE DATEPART(YEAR,CURRENT_TIMESTAMP) <= DATEPART(YEAR,FECHA) AND NUMSERIE LIKE 'A%'
GROUP BY CONCAT(DATEPART(MONTH,FECHA),'-',DATEPART(YEAR,FECHA))
)
SELECT *
FROM TABLE_CURRENT, TABLE_LAST
When I run the query I get exactly the square of the result.
I want to compare sale monthly with last year.
2-2020 814053.3 2-2019 840295.1
1-2020 1094993.65 2-2019 840295.1
3-2020 293927.3 2-2019 840295.1
2-2020 814053.3 1-2019 1050701.68
1-2020 1094993.65 1-2019 1050701.68
3-2020 293927.3 1-2019 1050701.68
2-2020 814053.3 3-2019 887776.1
1-2020 1094993.65 3-2019 887776.1
3-2020 293927.3 3-2019 887776.1
I should get only 3 rows instead of 9 rows.
You need to properly join your two CTE - the way you're doing it now, you're getting a Cartesian product of each row in either CTE together.
Do something like:
*;WITH TABLE_LAST AS
( ....
),
TABLE_CURRENT AS
( ....
)
SELECT *
FROM TABLE_CURRENT curr
INNER JOIN TABLE_LAST last ON (some join condition here)
What that join condition is going to be - I have no idea, and cannot tell from your question - but you have to define how these two sets of data "connect" ....
It could be something like:
SELECT *
FROM TABLE_CURRENT curr
INNER JOIN TABLE_LAST last ON curr.CURR_YEAR_MONTH = last.LAST_YEAR_MONT
or whatever else makes sense in your situation - but basically, you need to somehow "tie together" these two sets of data and get only those rows that make sense - not just every row from "last" combined with every row from "curr" ....
While you already got the answer on how to join the two results, I thought I'd tell you how to typically approach such problems.
From the same table, you want two sums on different conditions (different years that is). You solve this with conditional aggregation, which does just that: aggregate (sum) based on a condition (year).
select
datepart(month, fecha) as month,
sum(case when datepart(year, fecha) = datepart(year, getdate()) then totalneto end) as this_year,
sum(case when datepart(year, fecha) = datepart(year, getdate()) -1 then totalneto end) as last_year
from albventacab
where numserie like 'A%'
and fecha > dateadd(year, -2, getdate())
group by datepart(month, fecha)
order by datepart(month, fecha);

PIVOT table returning all null data

Consider this query:
SELECT *
FROM (
SELECT
userid,
FORMAT(datecreated, 'yyyy-MM') AS purchasemonth,
COALESCE(amount + tip, 0) AS amt
FROM invoice
) AS SourceTable
which produces output like this:
And this pivot query in which I am trying to sum over each month:
SELECT
userid,
COALESCE([2016-08-01], 0) AS [2016-08-01],
COALESCE([2016-09-01], 0) AS [2016-09-01]
FROM (
SELECT
userid,
FORMAT(datecreated, 'yyyy-MM') AS purchasemonth,
COALESCE(amount + tip, 0) AS amt
FROM invoice
) AS SourceTable
PIVOT
(
SUM(amt)
FOR purchasemonth IN ([2016-08-01], [2016-09-01])
) AS PivotTable
which produces output like this:
There is no NULL data at all in the original query's output. The PIVOT query's output is nothing but null data (coalesced to 0). But I can't figure out why the PIVOT is not summing the data as I expected. I'm expecting there to be no NULL data in the PIVOT output either.
How can I fix the query to behave as expected?
PurchaseMonth in your Derived Table is a String without DAYs in it and you are comparing it to a Date with days in it for the values/column names:
So the main issue is this line:
FOR purchasemonth IN ([2016-08-01], [2016-09-01])
TO
FOR purchasemonth IN ([2016-08], [2016-09])
Once you change that you would need to change the COALESCE() statements too
and you should get what you want.
SELECT
userid,
COALESCE([2016-08], 0) AS [2016-08-01],
COALESCE([2016-09], 0) AS [2016-09-01]
FROM (
SELECT
userid,
FORMAT(datecreated, 'yyyy-MM') AS purchasemonth,
COALESCE(amount + tip, 0) AS amt
FROM invoice
) AS SourceTable
PIVOT
(
SUM(amt)
FOR purchasemonth IN ([2016-08], [2016-09])
) AS PivotTable
If you want the 01 to remain for days then simply change up the Derived Table definition to be a date or include the day in the format
So if you want to go this route change this line:
FORMAT(datecreated, 'yyyy-MM') AS purchasemonth,
To
DATEADD(day,1-DAY(datecreated),datecreated) AS purchasemonth,
you could also use this
FORMAT(datecreated, 'yyyy-MM-dd') AS purchasemonth,
But FORMAT has performance impacts that you have no reason to introduce if you don't need to.
SELECT
userid,
COALESCE([2016-08-01], 0) AS [2016-08-01],
COALESCE([2016-09-01], 0) AS [2016-09-01]
FROM (
SELECT
userid,
DATEADD(day,1-DAY(datecreated),datecreated) AS purchasemonth,
COALESCE(amount + tip, 0) AS amt
FROM invoice
) AS SourceTable
PIVOT
(
SUM(amt)
FOR purchasemonth IN ([2016-08-01], [2016-09-01])
) AS PivotTable

Showing all results even using GROUP BY CLAUSE

Query :
How to sort by months ?
select format(datee,'mmm-yyyy') as [Months],sum(amount) as Amount
from ledger_broker
where ref_from like 'Purchase'
group by format(datee,'mmm-yyyy')
order by format(datee,'mmm-yyyy') desc
Output :
Try grouping by the same exact column which you select:
SELECT t.[Months], t.Amount
FROM
(
SELECT MONTH(datee) AS theMonth, YEAR(datee) AS theYear,
FORMAT(datee,'mmm-yyyy') AS [Months], SUM(amount) AS Amount
FROM ledger_transporter
WHERE ref_from LIKE 'Purchase'
GROUP BY MONTH(datee), YEAR(datee), FORMAT(datee, 'mmm-yyyy')
) t
ORDER BY t.theYear DESC, t.theMonth DESC
One way to order by date is to select the numeric month and year in your query.
change group by datee to group by format(datee,'mmm-yyyy').
select distinct format(datee,'mmm-yyyy') as [Months], sum(amount) as Amount
from ledger_transporter
where ref_from like 'Purchase'
group by format(datee,'mmm-yyyy')
order by Month(datee)
The reason is that your date, which I assume is say 01-FEB-2016 and 02-FEB-2016, is different and if you group by it, you will get 2 different records for it.
However, for format(datee,'mmm-yyyy'), ie FEB-2016, both of these dates are same. Hence the mismatch

ORDER BY, set a specific case to the first index?

Using SQL Server 2008...
I'm having some troubles in trying to order my rows in a specific order that I would like them to be ordered by. I've found a few examples that use the ORDER BY CASE clause, but am unsure whether using this method will produce the result that I want it to, thus I come to the community!
Here's what I have:
First, I select, if it exists, a distinct year that is equal to the current year:
IF EXISTS(SELECT DISTINCT [Year]
FROM Assessment WHERE ProjectCode = #ProjectCode AND [Year] = DATENAME(YEAR, GETDATE()))
SELECT DISTINCT [Year]
FROM Assessment WHERE ProjectCode = #ProjectCode
But, then I find some confusion in ordering the results. I'd like to set the current year to the first row returned using the ORDER BY clause, then order the rest of the returned years in a descending order, here's what I have so far:
ORDER BY (CASE WHEN [Year] = (DATENAME(YEAR, GETDATE())) THEN 1
ELSE 100 END) ASC, [Year] desc
Next, if the current year is not contained in the query, select each year and order by year descending.
ELSE
SELECT DISTINCT [Year]
FROM Assessment WHERE ProjectCode = #ProjectCode
ORDER BY [Year] desc
Thanks, in advance!
You don't need conditional statements here at all:
SELECT *
FROM (
SELECT DISTINCT [Year]
FROM Assessment
WHERE projectCode = #projectCode
) q
ORDER BY
CASE [Year] WHEN YEAR(GETDATE()) THEN 1 ELSE 2 END,
[Year]
will output the current year (if exists) first, the other later.
You're question isn't very clear because you don't specify what is broken or where you're having issues. From what I gather, however, you don't need an IF/ELSE. Instead you could do something like ...
SELECT DISTINCT [Year],
CASE [Year]
WHEN DATENAME(Year, GETDATE()) THEN 9999
ELSE [Year] END AS GarbageSoDistinctWorks
FROM Assessment
WHERE ProjectCode = #ProjectCode
ORDER BY
CASE [Year]
WHEN DATENAME(Year, GETDATE()) THEN 9999
ELSE [Year] END DESC
FYI ... i added the case to the select list as a throw away column to avoid the error I assume you're getting.. There are other ways, like a derived table, but for now this should work..
Msg 145, Level 15, State 1, Line 2
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
HTH,
-eric
Your example code appears to do what you describe. What problems are you having?
As a side note: You don't need the IF statement. By using the ORDER BY from your first example (with the CASE statement), you will get the correct results for both scenarios.
- If "this year" is in your data, it comes first. Everything else comes next in DESC order
- If "this year" isn't in your data, you just get everything else in DESC order