How to SUM values from two columns - sql

I have the following information in a table
Load Number Origin Destination
1 AR TX
2 AR AL
3 TX MS
4 WA AR
I need help with a SQL statement that will produce the follow results
State Origin Destination
AR 2 1
TX 1 1
WA 1
MS 1
I have tried countless types of SELECT statements with various types of COUNTS in them and GROUP BY's at the end but I can't get the results I'm looking for. Any help is greatly appreciated.

How about:
select state,
sum(origin) origin,
sum(destination) destination
from (select origin as state,
0 as destination,
1 as origin
from my_table
union all
select destination,
1,
0
from my_table)
group by state

You can first build a inner query to select all the distinct states from Origin and Destination columns. Then you can join it back to the main table and do a conditional aggregation.
Demo
select x.state,
sum(case when x.state = t.Origin then 1 end),
sum(case when x.state = t.Destination then 1 end)
from tablename t
join (
select Origin as State
from tablename
union
select Destination
from tablename ) x
on t.Origin = x.state or t.Destination = x.state
group by x.state

Related

aliasing pivot column

i am trying to alias the pivot column to scenario1, scenario2, scenario3 instead of 1,2,3. I am getting error.
select *
from (select *
from (select s.campaign_id campaign_id, s.scenario_index scenario_index
from scenario s, campaign c where s.campaign_id = c.campaign_id)
pivot (max(scenario_index)for scenario_index in (1,2,3))
)a
thank you, aggregation gives the result with alias now. The requirement i have is to combine these columns with another query which is
select CASE WHEN AWARD_TYPE = 0 THEN award_rate||' points'
when AWARD_TYPE = 1 then Award_rate||' %'
when award_type=2 then RATIO_POINTS||' points per '||RATIO_MON_UNIT||' AED' End
from points_rule p
where c.pt_basic_rule_id = p.point_rule_id ) as pool_awards,
this query comes as a column and then the scenario1, 2,3 should come as 3 columns with the value of the pool_award based on the campaign_id
Just use conditional aggregation:
select s.campaign_id,
max(case when scenario_index = 1 then 1 end) as scenario1,
max(case when scenario_index = 2 then 1 end) as scenario2,
max(case when scenario_index = 3 then 1 end) as scenario3
from scenario s join
campaign c
on s.campaign_id = c.campaign_id
group by campaign_id;
You can use an alias in IN clause of the PIVOT as follows:
select *
from (select *
from (select s.campaign_id campaign_id, s.scenario_index scenario_index
from scenario s, campaign c where s.campaign_id = c.campaign_id)
pivot (max(scenario_index)for scenario_index in (1 as scenario1,2 as scenario2,3 as scenario3))
)a

Get single row depending of conditional

I have a simple select query with some joins like:
SELECT
[c].[column1]
, [c].[column2]
FROM [Customer] AS [c]
INNER JOIN ...
So I do a left join with my principal table as:
LEFT JOIN [Communication] AS [com] ON [c].[CustomerGuid] = [com].[ComGuid]
this relatioship its 1 to *, one customer can have multiple communications
So in my select I want to get value 1 or 2 depending of condition:
Condition:
if ComTypeKey (from communication) table have a row with value 3 and have another row with vale 4 return 1 then 0
So I try something like:
SELECT
[c].[column1]
, [c].[column2]
, IIF([com].[ComTypeKey] = 3 AND [com].[ComTypeKey] = 4,1,0)
FROM [Customer] AS [c]
INNER JOIN ...
LEFT JOIN [Communication] AS [com] ON [c].[CustomerGuid] = [com].[ComGuid]
But it throws me two rows, beacause there are 2 rows on communication. My desire value is to get only one row with value 1 if my condition is true
If you have multiple rows you need GROUP BY, then count the relevant keys and subtract 1 to get (1, 0)
SELECT
[c].[column1]
, [c].[column2]
, COUNT(CASE WHEN [ComTypeKey] IN (3,4) THEN 1 END) - 1 as FLAG_CONDITION
FROM [Customer] AS [c]
INNER JOIN ...
LEFT JOIN [Communication] AS [com]
ON [c].[CustomerGuid] = [com].[ComGuid]
GROUP BY
[c].[column1]
, [c].[column2]
I'm not really sure I understand.
This will literally find if both values 3 and 4 exist for that CustomerGuid, and only select one of them in that case - not filtering out any record otherwise.
If this is not what you want, providing sample data with the expected result would remove the ambiguity.
SELECT Field1,
Field2,
...
FieldN
FROM (SELECT TMP.*,
CASE WHEN hasBothValues = 1 THEN
ROW_NUMBER() OVER ( PARTITION BY CustomerGuid ORDER BY 1 )
ELSE 1
END AS iterim_rn
FROM (SELECT TD.*,
MAX(CASE WHEN Value1 = '3' THEN 1 ELSE 0 END) OVER
( PARTITION BY CustomerGuid ) *
MAX(CASE WHEN Value1 = '4' THEN 1 ELSE 0 END) OVER
( PARTITION BY CustomerGuid ) AS hasBothValues
FROM TEST_DATA TD
) TMP
) TMP2
WHERE interim_rn = 1

SQL Multiple Rows in Singleton Select

I have the following SQL:
WITH G1 AS
(SELECT G.NUM_REFE, G.GUIA AS MASTER,
(SELECT H.GUIA FROM SAAIO_GUIAS H WHERE G.NUM_REFE = H.NUM_REFE AND H.IDE_MH ="H" AND H.CONS_GUIA="1" ) AS HOUSE
FROM SAAIO_GUIAS G WHERE G.IDE_MH ="M" AND G.CONS_GUIA ="1" )
SELECT
*
FROM G1
And it returns the error
"Multiple Rows in Singleton Select".
This is a sample of the database
Any hint will be deeply appreciated
Thanks
Your query wants to retrieve the one matching GUIA, but it seems there can be multiple entries per NUM_REFE for IDE_MH = 'H' AND CONS_GUIA = 1. Check this with
select num_refe
from saaio_guias
where ide_mh = 'H'
and cons_guia = 1
group by num_refe
having count(*) > 1;
This should give no results, but it probably does. And if it does then it cannot work for your query and you must think about which value to pick in this case. Maybe simply the minimum or maximum:
(
select min(h.guia)
from saaio_guias h
...
Or maybe you want to delete rows from the table that you consider duplicates and add a constraint (unique index on num_refe + ide_mh + cons_guia) to prevent from such records in the future.
Your query can be written simpler using conditional aggregation by the way:
select
num_refe,
any_value(case when ide_mh = 'M' then guia end) as master,
any_value(case when ide_mh = 'H' then guia end) as guia
from saaio_guias
where cons_guia = 1
group by num_refe
order by num_refe;
Thie problem is in CTE SELECT Subquery.
I think you can use CASE express instead of SELECT Subquery
WITH G1 AS
(
select
num_refe,
Case when ide_mh = 'M' then GUIA ELSE '' END as MASTER,
Case when ide_mh = 'H' then GUIA ELSE '' END as HOUSE
from saaio_guias
where cons_guia = 1
)
SELECT
*
FROM G1
OR
SELECT G.NUM_REFE, G.GUIA AS MASTER,H.GUIA
FROM SAAIO_GUIAS G
INNER JOIN
(
SELECT *
FROM SAAIO_GUIAS
WHERE IDE_MH ='H' AND CONS_GUIA='1'
) AS H ON G.NUM_REFE = H.NUM_REFE
WHERE G.IDE_MH ='M' AND G.CONS_GUIA ='1'
I don't know what is your expect result.So I guess these two query might help you.

Select multiple counts from one database table in one sql command access

I have a single table in the following format:
STATE SURVEY_ANSWER
NC high
NC moderate
WA high
FL low
NC high
I am looking for a single query that will get me the following result:
STATE HIGH MODERATE LOW
NC 2 1 0
WA 1 0 0
FL 0 0 1
Unfortunately, these are the results I am getting:
STATE HIGH MODERATE LOW
NC 3 1 1
WA 3 1 1
FL 3 1 1
Here is the code I am using:
Select mytable.STATE,
(SELECT COUNT(*) FROM mytable WHERE mytable.survey_answer = 'low' and state = mytable.state) AS low,
(SELECT COUNT(*) FROM mytable WHERE mytable.survey_answer = 'moderate' and state = mytable.state) AS moderate,
(SELECT COUNT(*) FROM mytable WHERE mytable.survey_answer = 'high' and state = mytable.state) AS high,
FROM mytable
GROUP BY mytable.state;
While this and other forums have been very helpful I am unable to figure out what I am doing wrong. PLEASE NOTE: I am using Access so CASE WHEN solutions do not work. Thank you for any advice.
It looks like this may be an issue caused by not using table aliases. Because you are doing sub-queries on the same table that the outer SELECT is using and not giving the outer table an alias, both of the conditions in the WHERE of the sub-query are only using data in the sub-query.
In other words, when you write:
SELECT COUNT(*) FROM mytable WHERE mytable.survey_answer = 'low' and state = mytable.state
It doesn't know anything about the outer query.
Try this:
SELECT t1.STATE,
(SELECT COUNT(*) FROM mytable t2 WHERE t2.state = t1.state AND t2.survey_answer = 'low') low,
(SELECT COUNT(*) FROM mytable t3 WHERE t3.state = t1.state AND t3.survey_answer = 'moderate') moderate,
(SELECT COUNT(*) FROM mytable t4 WHERE t4.state = t1.state AND t4.survey_answer = 'high') high,
FROM mytable t1
GROUP BY t1.state
Aiias answer explains why your current query is not working, but I thought I'd point out that your assumption that you can't use CASE WHEN solutions is only partly right, yes you can't use CASE WHEN but that doesn't mean you need correlated subqueries. You could simply use:
SELECT mytable.STATE,
SUM(IIF(mytable.survey_answer = 'low', 1, 0) AS low,
SUM(IIF(mytable.survey_answer = 'moderate', 1, 0) AS moderate,
SUM(IIF(mytable.survey_answer = 'high', 1, 0) AS high
FROM mytable
GROUP BY mytable.state;

Select Distinct Attribute and Print out Count of another even when the count is 0

I don't quite know how I should describe the problem for title, but here's my question.
I have a table named hello with two columns named time and state.
Time | State
Here's an example of the data I have
1 DC
1 VA
1 VA
2 DC
2 MD
3 MD
3 MD
3 VA
3 DC
I would like to get all the possible time and the count of "VA" (0 if "VA" doesn't appear at the time)
The output would look like this
Time Number
1 2
2 0
3 1
I tried to do
SELECT DISTINCT time,
COUNT(state) as Number
FROM hello
WHERE state = 'VA'
GROUP BY time
but it doesn't seem to work.
This is a conditional aggregation:
select time, sum(case when state = 'VA' then 1 else 0 end) as NumVA
from hello
group by time
I want to add that you should never use distinct when you have a group by. The two are redundant. Distinct as a keyword is not even needed in the SQL language; semantically, it is just shorthand for grouping by all the columns.
SELECT TIME,
SUM(CASE WHEN State = 'VA' THEN 1 ELSE 0 END)
FROm tableName
GROUP BY Time
SQLFiddle Demo
One rule of thumb is to get your counts first and put them into a temp for use later.
See below:
Create table temp(Num int, [state] varchar(2))
Insert into temp(Num,[state])
Select 1,'DC'
UNION ALL
Select 1,'VA'
UNION ALL
Select 1,'VA'
UNION ALL
Select 2,'DC'
UNION ALL
Select 2,'MD'
UNION ALL
Select 3,'MD'
UNION All
Select 3,'MD'
UNION ALL
Select 3,'VA'
UNION ALL
Select 3,'DC'
Select t.Num [Time],t.[State]
, CASE WHEN t.[state] = 'VA' THEN Count(t.[State]) ELSE 0 END [Number]
INTO #temp2
From temp t
Group by t.Num, t.[state]
--drop table #temp2
Select
t2.[time]
,SUM(t2.[Number])
From #temp2 t2
group by t2.[time]