Query returns two lines - sql-server

I have a table that has a column called type which has either a value of invoiced or order and then another column holding the value along with a column holding the customer number etc.
I have written a script :-
select
customer,
(CASE WHEN TYPE = 'INVOICED' THEN SUM(INVTOTAL) else 0 END) AS INVTOTAL,
(CASE WHEN TYPE = 'ORDERS' THEN SUM(INVTOTAL) else 0 END) AS ORDERTOTAL
from
salestable
Why does it return the following?
customer INVTOTAL ORDERTOTAL
Joe Bloggs 1000 0
Joe Bloggs 0 1300
instead of
customer INVTOTAL ORDERTOTAL
Joe Bloggs 1000 1300
Sorry to ask such a novice question but I am new to SQL and learning it...
Thanks for any help!

Your query was missing a group by. Also use sum around case to avoid multiple rows.
select customer,
sum(CASE WHEN TYPE = 'INVOICED' THEN INVTOTAL else 0 END) AS INVTOTAL,
sum(CASE WHEN TYPE = 'ORDERS' THEN INVTOTAL else 0 END) AS ORDERTOTAL
from salestable
group by customer

You need to do a group by with the customer that will avoid the multiple rows.check the fiddle below.
create table tb1
(customer varchar(25),
type varchar(25),
invoice numeric(18,2)
);
insert into tb1(customer,type,invoice) values('Joe Bloggs','INVOICED',1000);
insert into tb1(customer,type,invoice) values('Joe Bloggs','ORDERS',1000);
select customer,
sum(CASE WHEN TYPE = 'INVOICED' THEN sum(invoice) else 0 END) AS INVTOTAL,
sum(CASE WHEN TYPE = 'ORDERS' THEN sum(invoice) else 0 END) AS ORDERTOTAL
from tb1
group by customer
fiddle with example
You need to put the entire case statment inside sum()
inorder to avoid grouping by type also else you will get this below error
Column 'tb1.type' is invalid in the select list because it is
not contained in either an aggregate function or the GROUP BY clause.

Because select returns a row for each row in the table matching the where filters. If no filters, then a result row for every row in table. If you want to "join" the rows, you could try grouping by the customer, like:
SELECT customer,
SUM(CASE WHEN TYPE = 'INVOICED' THEN INVTOTAL ELSE 0 END) as INVTOTAL,
SUM(CASE WHEN TYPE = 'ORDERS' THEN INVTOTAL ELSE 0 END) as ORDERTOTAL
FROM salestable
GROUP BY customer

Related

Sum of a column in snowflake

I have two calculated columns with case statements. Now, I need to take Sum of those columns and need the difference in it.
For Ex.
Select Case when account = '30' and status='active' then value as value1,
case when account = '31' and status='active' then value as value2,
Sum(value1) - Sum(Value2) as Total_SUM
from table
How can we achieve this.. This gives me a missing group by clause error. I tried many things but did not work out.
Use conditional aggregation and sum the CASE expressions:
SELECT
SUM(CASE WHEN account = '30' THEN value ELSE 0 END) AS value1,
SUM(CASE WHEN account = '31' THEN value ELSE 0 END) AS value2,
SUM(CASE WHEN account = '30' THEN value ELSE 0 END) -
SUM(CASE WHEN account = '31' THEN value ELSE 0 END) AS Total_SUM
FROM yourTable
WHERE status = 'active';

Define a relationship as a union

In several parts of my code I have for example these lines:
$user->movements()->get();
...
$user->movements()->where(...)->get();
...
$user->movements()->where(...)->select(... sum, count, avg ...)->get();
...
But now I'm facing an important change on the movements table structure.
Now I need two tables with a similar structure (the data HAVE to be in separate tables), movements and ticket_movements.
These tables are consulted by two system, one of then needs the data to be separated and the other needs the data to be as in one table.
So, in one of the systems, I would like to define the relationship movements() as an union of movements and ticket_movements tables.
So, having the relationship movements defined as:
public function movements()
{
$movements = $this->hasMany('App\Model\Movement')
->select(\DB::raw("
id,
user_id,
movement_type_id,
amount,
description
"));
$tickets_movements = $this->hasMany('App\Model\TicketMovement')
->select(\DB::raw("
id,
user_id,
movement_type_id,
amount,
description
"));
return $movements->union($tickets_movements->getQuery());
}
If I do this:
$user->movements()
->whereIn('movement_type_id', [1, 2])
->select(\DB::raw('
SUM(CASE WHEN movement_type_id = 1 THEN 1 ELSE 0 END) as credit,
SUM(CASE WHEN movement_type_id = 2 THEN 1 ELSE 0 END) as debit
'))
->first();
The query I get is:
SELECT
SUM(CASE WHEN movement_type_id = 1 THEN 1 ELSE 0 END) as credit,
SUM(CASE WHEN movement_type_id = 2 THEN 1 ELSE 0 END) as debit
FROM "movements"
WHERE "movements"."user_id" = 2
AND "movements"."user_id" is not null
AND "movement_type_id" in (1, 2)
UNION
SELECT id, user_id, movement_type_id, amount, description
FROM "ticket_movements"
WHERE "ticket_movements"."user_id" = 2
AND "ticket_movements"."user_id" is not null limit 1
Besides it's not the query I need, it give me an error because of the columns:
Syntax error: 7 ERROR:
each UNION query must have the same number of columns
The query I need is something like this:
SELECT
SUM(CASE WHEN movement_type_id = 1 THEN 1 ELSE 0 END) as credit,
SUM(CASE WHEN movement_type_id = 2 THEN 1 ELSE 0 END) as debit
FROM (
SELECT id, user_id, movement_type_id, amount, description
FROM "movements"
UNION
SELECT id, user_id, movement_type_id, amount, description
FROM "ticket_movements" ) as movements
WHERE "movements"."user_id" = 2
AND "movements"."movement_type_id" in (1, 2)
Without modifying each line where I do $user->movements()...
I don't know is that is possible...

Passing values into CASE statement

and thank you all in advance for your help.
I'm trying to take the results from two separate queries and include them in a third query that has a CASE statement. I've had some success but I'm not able to present the results of the third query in the proper order. The purpose of this is to show the employee count for each department under the different managers. So far I can only load separately the manager names and their departments and employee department count totals by department. What I can't figure out is how to get the manager names in and the employee department count in for each manager row. Below are the two source queries I've used so far and the query with the CASE statement. I've also looked at UNPIVOT function with no success yet.
a) This simple query lists each primary manager name. There are also sub managers that will be returned using a hierarchy query later.
select name from employees "Boss" where employeeid in
(‘1’,'5','25','84','85');
b) This query returns the department id count for each main manager (‘1’,'5','25','84','85') as well as all sub-managers.
select departmentid, count(departmentid) COUNT from employees
where departmentid = departmentid and level <= 3
connect by prior employeeid = bossid
start with employeeid = 5
group by departmentid
order by departmentid;
c) Here’s a CASE statement that outputs exactly as desired. The problem here is the select statement currently outputs only the manager names and the manager departments into the columns. What I need to do is output both the manager names and the manager's employee department counts into the individual manager row columns. I've tried to do a separate select of the manager names to get the ‘Boss’ column and another select to include the department counts. But that got messy. Also passing the counts in a second statement would create an additional unwanted column.
select e.name "Boss",
COUNT(CASE WHEN d.departmentid = '1' THEN 1 END) AS "Finance",
COUNT(CASE WHEN d.departmentid = '2' THEN 1 END) AS "HR",
COUNT(CASE WHEN d.departmentid = '3' THEN 1 END) AS "IT",
COUNT(CASE WHEN d.departmentid = '4' THEN 1 END) AS "Marketing",
COUNT(CASE WHEN d.departmentid = '5' THEN 1 END) AS "Sales"
from employees e, departments d
where e.employeeid in (select distinct e.bossid from employees e)
and e.departmentid = d.departmentid (+)
group by e.name
order by e.name;
Boss Finance HR IT Marketing Sales
-------------------- ---------- ---------- ---------- ---------- ----------
Baxter Carney 0 0 0 0 1
Blythe Pierce 0 0 0 0 1
Here's an altered CASE query that loads the employee department counts but unfortunately it loads by department and not by individual manager. That is the problem I'm stuck on right now. How to pass the counts to the right manager and into the right column.
select departmentid "DEPTNO",
COUNT(CASE WHEN departmentid = '1' THEN 1 END) AS "Finance",
COUNT(CASE WHEN departmentid = '2' THEN 1 END) AS "HR",
COUNT(CASE WHEN departmentid = '3' THEN 1 END) AS "IT",
COUNT(CASE WHEN departmentid = '4' THEN 1 END) AS "Marketing",
COUNT(CASE WHEN departmentid = '5' THEN 1 END) AS "Sales"
from employees
where departmentid = departmentid and level <= 3
connect by prior employeeid = bossid
start with employeeid = 5
group by departmentid
order by departmentid
/
DEPTNO Finance HR IT Marketing Sales
3 0 0 1 0 0
5 0 0 0 0 21
And here's for all managers. You can see that it just keeps increasing the individual department count.
DEPTNO Finance HR IT Marketing Sales
1 4 0 0 0 0
2 0 23 0 0 0
3 0 0 20 0 0
4 0 0 0 1 0
5 0 0 0 0 28

SQL Server Query that returns the number of Likes and number of Dislikes

I have a SQL server table that displays what a user Liked or Disliked in an item description. He/she can only like/dislike one item so it will display a 1 if Liked or 0 if Disliked on the Type Field.
What I want is for an output that counts the Likes and Dislikes that displays both of them as seen below. I tried to do inner joins and unions and can't get it to work. Any ideas?
SELECT ItemID,
Description,
SUM(CASE WHEN Type = 1 THEN 1 ELSE 0 END) AS Like,
SUM(CASE WHEN Type = 0 THEN 1 ELSE 0 END) AS Dislike
FROM Table
GROUP BY ItemID,
Description
try:
select ItemId,Description, sum(case when Type=1 then 1 else 0 end) 'like', // quote the word like
sum(case when Type = 0 then 1 else 0 end) 'dislike'
from tblFeedback
group by ItemId

SQL Server: pivoting across multiple colums

I have a serious problem. Say my data is arranged in this format:
Name Businees_unit Forecast Upside
Jack.N India 100 50
Jack.N China 250 20
I have to pivot Forecast and Upside for Business_Unit so the table will look like this
Name Forecast_India Upside_India Forecast_China Upside_China
Jack 100 50 250 20
Can this be done in one query?
Its my first entry, so any help is very welcomed.
Thanks
A generic solution:
select name,
sum(case when Businees_unit = 'India' then Forecast else 0 end) Forecast_India,
sum(case when Businees_unit = 'India' then Upside else 0 end) Upside_India,
sum(case when Businees_unit = 'China' then Forecast else 0 end) Forecast_China,
sum(case when Businees_unit = 'China' then Upside else 0 end) Upside_China
from My_table
group by name
I would use self join:
SELECT DISTINCT SomeTable.Name, China.Forecast as Forecast_China, China.Upside as Upside_China
, India.Forecast as Forecast_India, India.Upside as Upside_India
FROM SomeTable
inner join SomeTable India on India.Name = SomeTable.Name AND India.Business_unit = 'India'
inner join SomeTable China on China.Name = SomeTable.Name AND China.Business_unit = 'China'

Resources