Remove query results with having - sql

I have an SQL query like the following:
select aaa,
count(condition_1),
count(condition_2),
count(condition_3)
from DB
where ...
group by 1,
order by 1
The above will return four columns. Is it possible with a having statement to suppress some of the fields in the results but return all the rows that the original script would produce.
Thanks in advance for your help

if you are trying to "suppress" field values (and i assume that you're really looking to return 0 in that case, since the fields aren't going away as long as they're in the select) based on some criteria but return all rows, you could try the following:
select aaa,
case when count(condition_1) > 1 then count(condition_1) else 0 end as count_1,
case when count(condition_2) > 1 then count(condition_2) else 0 end as count_2,
case when count(condition_3) > 1 then count(condition_3) else 0 end as count_3
from DB
where ...
group by 1,
order by 1
obviously modify the case statements to reflect the values you wish to return, with all others being 0

I am not exactly sure what you mean but, from my understanding you are trying to group your results based on a single column's count. If that's right, then the code you need would be along the lines of
select aaa,
count(condition_1) as count_1,
count(condition_2) as count_2,
count(condition_3) as count_3
from DB
where ...
group by 1,
order by 1
having count_1 > 1

No, you can't suppress columns (fields) and keep all the rows.
Any filtering (WHERE, HAVING etc) will apply only to rows.
You could do this
select
aaa,
case
when somecondition then count(condition_1)
when somecondition then count(condition_2)
end as thecount,
case
when somecondition then '1'
when somecondition then '2'
end as thecountofwhat
from mytable
where ...
group by aaa,
order by aaa
Note: don't use ordinals in GROUP BY or ORDER BY. Bad practice. And only MySQL allows such nonsense in the GROUP BY.

Related

AND OR SQL operator with multiple records

I have the following query where if brand1/camp1 taken individually, query returns the correct value but if I specify more than one brand or campaigns, it returns some other number and I am not sure what the math is behind that. It is not the total of the two either.
I think it is IN operator that is specifying OR with "," as opposed to what I require it to do which is consider AND
select campaign,
sum(case when campaign in ('camp1', 'camp2') and description in ('brand1', 'brand2') then orders else 0 end) as brand_convs
from data.camp_results
where campaign in ('camp1', 'camp2') and channel='prog' and type='sbc'
group by campaign
having brand_convs > 0
order by brand_convs desc;
Any thoughts?
The problem is in the IN part as you suspected: The two IN operators do not affect eachother in any way, so campaign can be camp1 while description is brand2.
If your DBMS supports multiple columns in an IN statement, you use a single IN statement:
SELECT campaign, SUM(
CASE WHEN (campaign, description) IN (
('camp1', 'brand1'),
('camp2', 'brand2')
) THEN orders ELSE 0 END
) [rest of query...]
If not, you're probably going to have to use ANDs and ORs
SELECT campaign, SUM(
CASE WHEN
(campaign='camp1' AND description='brand1')
OR (campaign='camp2' AND description='brand2')
THEN orders ELSE 0 END
) [rest of query...]

Update column within CASE statement with results of a subquery postgres

I need to update a column based on the results of a subquery. If the subquery returns results for that column then the columns must be updated, is the query returns no results for that column then I need to update with 0.
I do not know where to place the subquery and how to combine it with the CASE statement. This is what I thought but the syntax is not correct. Can anybody help please?
(SELECT datazones.ogc_fid, count(*) as total
FROM suppliersnew suppliers, datazone_report_resupply datazones
WHERE St_contains(datazones.geom, suppliers.geometry) AND (suppliers.status = 'Under construction' OR
suppliers.status = 'Unknown' OR suppliers.status = 'Operational') GROUP by datazones.ogc_fid ORDER BY total ASC) sources
UPDATE datazone_report_resupply
SET es_actual =
CASE
WHEN datazone_report_resupply.ogc_fid = sources.ogc_fid THEN sources.total
ELSE 0
END
The query is a little hard to follow, because the aggregation is on the outer column (this is unusual). However, you don't need aggregation or order by. You only seem to care whether a row exists.
I think the logic is:
UPDATE datazone_report_resupply r
SET es_actual =
(CASE WHEN EXISTS (SELECT 1
FROM suppliersnew s
WHERE St_contains(r.geom, s.geometry) AND
s.status IN ('Under construction', 'Unknown', 'Operational')
)
THEN 1 ELSE 0
END);

How to add a column on fly ?

I am facing different kind of problem. In select query I want to add a temporary column on fly based on other columns value.
I have 2 columns
IsOpeningClosingDateToo (tinyint),
HearingDate Date
Now I want to check that if IsOpeningClosingDate = 1 then
Select HearingDate, HearingDate as 'OpeningDate'
If IsOpeningClosingDate= 2
Select HearingDate, HearingDate as 'ClosingDate'
I have tried to do this but failed:
SELECT
,[HearingDate]
,CASE [IsOpeningClosingDate]
when 1 then [HearingDate] as OpeningDate
When 0 then [HearingDate] as ClosingDate
end as 'test'
]
FROM [LitMS_MCP].[dbo].[CaseHearings]
I would suggest returning three columns. Then you can fetch the values in on the application side:
SELECT HearingDate,
(CASE WHEN IsOpeningClosingDate = 1 THEN HearingDate END) as OpeningDate,
(CASE WHEN IsOpeningClosingDate = 0 THEN HearingDate END) as ClosingDate
FROM [LitMS_MCP].[dbo].[CaseHearings];
Alternatively, you could just fetch HearingDate and IsOpeningClosingDate and do the comparison in Python.
The important point is that the columns in a SQL query are fixed by the SELECT. You cannot vary the names or types of the columns conditionally within the query.

changing positions of sql query results

The title is not claryifying my problem but this is how i could describe it.
I have a query which returns the following result :
and i was wondering if there is a way to reduce the number of lines from three to one having all the three no null values ( 400, 1000 and 21820 in one line ) with banquet as description.
Thank you for reading.
PS: this is just a capture of a part of the query results and there are a lot of duplicated lines. i can post my query if it would be helpful. i'm using some select case there..
EDIT:
THANK YOU guys but i solved that by copying the results of the main query to input of another one and adding distinct and sum clauses
SELECT description, MAX(number1) AS number1, MAX(number2) AS number2)
FROM myTable
GROUP BY description
At last in Oracle, you can use "When"
Eg:
SELECT
DESCRIPTION,
CASE WHEN SUMPRICE1 IS NULL THEN
CASE WHEN SUMPRICE2 IS NULL THEN
CASE WHEN SUMPRICE3 IS NULL THEN
0
ELSE SUMPRICE3 END
ELSE SUMPRICE2 END
ELSE SUMPRICE1 END AS SUMPRICE
FROM MY_TABLE
GROUP BY DESCRIPTION, SUMPRICE
Off course this is useble just if you have a static number of columns.
EDIT: I think I don't get the problem, but, if you don't want to merge the columns, you can use:
SELECT DESCRIPTION,
MAX(SUMPRICE1) AS SUMPRICE1,
MAX(SUMPRICE2) AS SUMPRICE2,
MAX(SUMPRICEN) AS SUMPRICEN
FROM MY_TABLE
GROUP BY DESCRIPTION
Or you can use the case to avoid the null, in the case of any of rows don't have a value:
SELECT DESCRIPTION,
CASE WHEN MAX(SUMPRICE1) IS NULL THEN 0 ELSE WHEN MAX(SUMPRICE1) END AS SUMPRICE1,
CASE WHEN MAX(SUMPRICE2) IS NULL THEN 0 ELSE WHEN MAX(SUMPRICE2) END AS SUMPRICE2,
CASE WHEN MAX(SUMPRICEN) IS NULL THEN 0 ELSE WHEN MAX(SUMPRICEN) END AS SUMPRICEN
FROM MY_TABLE
GROUP BY DESCRIPTION

SQL Server Update via Select Statement

I have the following sql statement and I want to update a field on the rows returned from the select statement. Is this possible with my select? The things I have tried are not giving me the desired results:
SELECT
Flows_Flows.FlowID,
Flows_Flows.Active,
Flows_Flows.BeatID,
Flows_Flows.FlowTitle,
Flows_Flows.FlowFileName,
Flows_Flows.FlowFilePath,
Flows_Users.UserName,
Flows_Users.DisplayName,
Flows_Users.ImageName,
Flows_Flows.Created,
SUM(CASE WHEN [Like] = 1 THEN 1 ELSE 0 END) AS Likes,
SUM(CASE WHEN [Dislike] = 1 THEN 1 ELSE 0 END) AS Dislikes
FROM Flows_Flows
INNER JOIN Flows_Users ON Flows_Users.UserID = Flows_Flows.UserID
LEFT JOIN Flows_Flows_Likes_Dislikes ON
Flows_Flows.FlowID=Flows_Flows_Likes_Dislikes.FlowID
WHERE Flows_Flows.Active = '1' AND Flows_Flows.Created < DATEADD(day, -60, GETDATE())
Group By Flows_Flows.FlowID, Flows_Flows.Active, Flows_Flows.BeatID,
Flows_Flows.FlowTitle, Flows_Flows.FlowFileName, Flows_Flows.FlowFilePath,
Flows_Users.UserName, Flows_Users.DisplayName, Flows_Users.ImageName,
Flows_Flows.Created
Having SUM(CASE WHEN [Like] = 1 THEN 1 ELSE 0 END) = '0' AND SUM(CASE WHEN [Dislike] = 1
THEN 1 ELSE 0 END) >= '0'
This select statement returns exactly what I need but I want to change the Active field from 1 to 0.
yes - the general structure might be like this: (note you don't declare your primary key)
UPDATE mytable
set myCol = 1
where myPrimaryKey in (
select myPrimaryKey from mytable where interesting bits happen here )
Because you haven't made your question more clear in what result you want to achieve, I'll provide an answer with my own assumptions.
Assumption
You have a select statement that gives you stuffs, and it works as desired. What you want it to do is to make it return results and update those selected rows on the fly - basically like saying "find X, tell me about X and make it Y".
Anwser
If my assumption is correct, unfortunately I don't think there is any way you can do that. A select does not alter the table, it can only fetch information. Similarly, an update does not provide more detail than the number of rows updated.
But don't give up yet, depending on the result you want to achieve, you have alternatives.
Alternatives
If you just want to update the rows that you have selected, you can
simply write an UPDATE statement to do that, and #Randy has provided
a good example of how it will be written.
If you want to reduce calls to server, meaning you want to make just
one call to the server and get result, as well as to update the
rows, you can write store procedures to do that.
Store procedures are like functions you wrote in programming languages. It essentially defines a set of sql operations and gives them a name. Each time you call that store procedure, the set of operations gets executed with supplied inputs, if any.
So if you want to learn more about store procedures you can take a look at:
http://www.mysqltutorial.org/introduction-to-sql-stored-procedures.aspx
If I understand correctly you are looking for a syntax to be able to select the value of Active to be 0 if it is 1. The syntax for something like that is
SELECT
Active= CASE WHEN Active=1 THEN 0 ELSE Active END
FROM
<Tables>
WHERE
<JOIN Conditions>