sql with logical operation - sql

hi here is my small problem . im working on sql and i have some logical operations to get the values from the sql database . i have the screen shot . plz refer it
in that i have four query in different combinations. if you take 1 and 2 both gives me the same answer and 3 and 4 gives me different answer . Now my question in i have two operators 1.OR and 2.And Not and the filters while means the variable may be n . now my question is
i want to get the different combinations for the given variables
and have to eliminate the possibility which gives me same result
any algorithms coding are welcome
can anyone help me soon
update
for more clear
if i have four values namely a,b,c,d
then i have to frame the diff combinations like
1. (a or b) and not( c or d)
2. a or ( b and not c ) or d
i have updated my question .. like this i have to generate different combination and get the answer

If you want to compare multiple rows within a set you can't use the logic you showed in your example, because a single row can't have multiple values within a singe column.
A common solution is to use aggregation over this group of rows and move the conditions into CASEs in HAVING checking if there's any row paasing the check:
e.g. your 2nd select,
(code = 40660 or code = 40900) and not code = 41180
can be simplified to
(code in (40660, 40900)) and code <> 41180
Translated into HAVING:
SELECT grpcol
FROM tab
GROUP BY grpcol
HAVING
-- any row with a code 40660 or 40900 --> result > 0 --> TRUE
SUM(CASE WHEN code IN (40660, 40900) THEN 1 ELSE 0 END) > 0
AND
-- any row with code 41180 --> result > 0 --> FALSE
SUM(CASE WHEN code <> 41180 THEN 1 ELSE 0 END) = 0

Related

Return a 0 if no rows are found in Microsoft SQL Server

I need your help with this query.
My table CSO_EMP_ORG_DPM_VIE has a column with different keys. Column name is EXT_KEY.
When I receive the same key number in EXT_KEY, I want the SQL code to count the duplicates using this query:
select EXT_KEY
from CSO_EMP_ORG_DPM_VIE
group by EXT_KEY
having count(*) > 1
This is working so far, but when it has no duplicate keys (numbers) in the column, I want it to generate it with 0 zero, and not nothing.
My expected result is; when two keys are the same I want to generate a 1. When no keys are the same, I want to generate an 0. Right now i got no result at all like in the screenshot.
How can I fix this SQL query accordingly?
Thank you in advance.
Use a CASE expression like this:
SELECT EXT_KEY,
CASE WHEN COUNT(*) > 1 THEN 1 ELSE 0 END flag
FROM CSO_EMP_ORG_DPM_VIE
GROUP by EXT_KEY
or if you want 1 result for the table:
SELECT CASE WHEN COUNT(EXT_KEY) > COUNT(DISTINCT EXT_KEY) THEN 1 ELSE 0 END flag
FROM CSO_EMP_ORG_DPM_VIE
It's not blindingly obvious as to what you are asking for. To that end, this query gives a 1/0 result based on having a count greater than 0 for each key...
SELECT
p.EXT_KEY,
EXT_KEY_RESULT = ISNULL((SELECT 1
FROM CSO_EMP_ORG_DPM_VIE c
WHERE c.EXT_KEY = p.EXT_KEY
HAVING COUNT(EXT_KEY) > 0), 0)
FROM
CSO_EMP_ORG_DPM_VIE p
Alternatively, if you are looking to count each of the keys, you could try...
SELECT EXT_KEY, COUNT(EXT_KEY)
FROM CSO_EMP_ORG_DPM_VIE
GROUP BY EXT_KEY
It's always good practice to specify a particular field in the COUNT aggregate, particularly the primary key, as it's faster to reference.
You really need to give us an expected result for your requirements and be very clear about your expectations.
SELECT CASE WHEN COUNT(EXT_KEY) > 0 THEN 1 ELSE 0 AS dupes
FROM CSO_EMP_ORG_DPM_VIE
PLEASE NOTE: Credit here to forpas for providing a smoother answer which I have borrowed.

Is it possible to select a column from a database and not display it in the result set - if selected, causes an issue with Group By

I have a query that's being use in my application. I had to make a small edit to it (select an additional column) and now that I do that, I don't get the same results, therefore I get a bad file. Just to give example this is what the query looks like ....
Select
'X' = tblA.VendorNumber,
'Y' = tblB.Label,
'Z' = tblC.InvoiceNo,
'W' = tblD.Checks,
From //Doing some joins here
Group By
tblA.VendorNumber, tblB.label, tblc.InvoiceNo, tblD.Checks
The result set gives me many records, but groups by the ones with identical X,Y,Z,W - so with no Group By it would look like this
X Y Z W
-----------------------------------------------------------
123 Anton 772 0
123 Anton 772 0
Obviously, with the group by they are rolled up into one...
The issue comes when I try to include an additional column in my Select query. I need this query in my, because I need to value in my code to be able to distinguish what type of record it is. With the new column, these two rows of data are not the same, therefore they do not get rolled up.
Is there a way for me to somehow add an additional column, but not display it, and exclude it from the Group By?
This is what I mean
Select
'X' = tblA.VendorNumber,
'Y' = tblB.Label,
'Z' = tblC.InvoiceNo,
'W' = tblD.Checks,
'P' = tblC.Proc -- New column
From //Doing some joins here
Group By
tblA.VendorNumber, tblB.label, tblc.InvoiceNo, tblD.Checks,
tblC.Proc -- New column
In this case the data looks like this
X Y Z W P
---------------------------------------------------------------------
123 Anton 772 0 FPN
123 Anton 772 0 PPN
So now that P is different for the 2 records that previously were rolled up into one, is there a way for me to somehow not display P, however, still be able to get it's value from my record set. I am unable to select the 'P' if it's not selected in this one query and because of the fact that the two records are not rolling up, I'm having some major issues.
Basically I need to select 'P' but not include it in my result set or group by.
Any help would be much appreciated.
There's a couple of options, I guess... There's not really a way to get values without having them in your results. How else would you read them?
One would be to STUFF the values of 'P' into a comma delimited list ie:
X Y Z W P
123 Anton 772 0 FPN,PPN
Then read them in your application separated by comma. Read here: https://stackoverflow.com/questions/31211506/how-stuff-and-for-xml-path-work-in-sql-server
Another would be to create boolean headers if there's not too many options for 'P' or you know all of the options. You can create them using CASE statements like:
,SUM(CASE WHEN tlbc.Proc = 'PPN' THEN 1 ELSE 0 END) AS "PPN"
EDIT: Left out an aggregate around it so it groups correctly. Can use MAX, for 1 or 0, as well... depends how many results there can be for tlbc.Proc. Some aggregate function around your cases will combine your rows to one.
For results like:
X Y Z W FPN PPN AnotherP
123 Anton 772 0 1 1 0
Third, if I misread your question and you don't need the values but just need them in a WHERE, then don't display them.
There's definitely more ways to go about this.
Does this help?
You need to do some sort of aggregate function on P so you don't need to group on it. If you only care about one of the values, you could use MIN() or MAX() to get one of them.
So, something like:
SELECT X, Y, Z, MAX(P) AS P etc....
Another way would be to use something like FOR XML PATH to pivot the values into a single value (maybe a comma separated list). There are lots of examples online of people doing this. Here is one example:
https://sqlperformance.com/2014/08/t-sql-queries/sql-server-grouped-concatenation
If you only want one record per first DISTINCT four column, which one of the P column you want to show?
If you have an answer for this question, just add to the query
Where tblC.Proc = -->YOUR_EXPECTED_VALUE_OR_CONDITION_HERE<--

PostgreSQL - Handling empty query result

I am quite new to SQL and I am currently working on some survey results with PostgreSQL. I need to calculate percentages of each option from 5-point scale for all survey questions. I have a table with respondentid, questionid, question response value. Demographic info needed for filtering datacut is retrieved from another table. Then query is passed to result table. All queries texts for specific datacuts are generated by VBA script.
It works OK in general, however there's one problematic case - when there are no respondents for specific cut and I receive empty table as query result. If respondent count is greater than 0 but lower than calculation threshold (5 respondents) I am getting table full of NULLs which is OK. For 0 respondents I get 0 rows as result and nothing is passed to result table and it causes some displacement in final table. I am able to track such cuts as I am also calculating respondent number for overall datacut and storing it in another table. But is there anything I can do at this point - generate somehow table full of NULLs which could be inserted into result table when needed?
Thanks in advance and sorry for clumsiness in code.
WITH ItemScores AS (
SELECT
rsp.questionid,
CASE WHEN SUM(CASE WHEN rsp.respvalue >= 0 THEN 1 ELSE 0 END) < 5 THEN
NULL
ELSE
ROUND(SUM(CASE WHEN rsp.respvalue = 5 THEN 1 ELSE 0 END)/CAST(SUM(CASE
WHEN rsp.respvalue >= 0 THEN 1 ELSE 0 END) AS DECIMAL),2)
END AS 5spercentage,
... and so on for frequencies of 1s,2s,3s and 4s
SUM(CASE WHEN rsp.respvalue >= 0 THEN 1 ELSE 0 END) AS QuestionTotalAnswers
FROM (
some filtering applied here [...]
) AS rsp
GROUP BY rsp.questionid
ORDER BY rsp.questionid;
INSERT INTO results_items SELECT * from ItemScores;
If you want to ensure that the questionid column won't be empty, then you must call a cte with its plain values and then left join with the table that actually you are using to make the aggregations, calcs etc. So it will generate for sure the first list and then join its values.
The example of its concept would be something like:
with calcs as (
select questionid, sum(respvalue) as sum_per_question
from rsp
group by questionid)
select distinct rsp.questionid, calcs.sum_per_question
from rsp
left join calcs on rsp.questionid = calcs.questionid

Return NULL instead of 0 when using COUNT(column) SQL Server

I have query which running fine and its doing two types of work, COUNT and SUM.
Something like
select
id,
Count (contracts) as countcontracts,
count(something1),
count(something1),
count(something1),
sum(cost) as sumCost
from
table
group by
id
My problem is: if there is no contract for a given ID, it will return 0 for COUNT and Null for SUM. I want to see null instead of 0
I was thinking about case when Count (contracts) = 0 then null else Count (contracts) end but I don't want to do it this way because I have more than 12 count positions in query and its prepossessing big amount of records so I think it may slow down query performance.
Is there any other ways to replace 0 with NULL?
Try this:
select NULLIF ( Count(something) , 0)
Here are three methods:
1. (case when count(contracts) > 0 then count(contracts) end) as countcontracts
2. sum(case when contracts is not null then 1 end) as countcontracts
3. nullif(count(contracts), 0)
All three of these require writing more complicated expressions. However, this really isn't that difficult. Just copy the line multiple times, and change the name of the variable on each one. Or, take the current query, put it into a spreadsheet and use spreadsheet functions to make the transformation. Then copy the function down. (Spreadsheets are really good code generators for repeated lines of code.)

SQL query cleanup - and/or based on condition

What I'm trying to do is write a query which, based on a boolean will select rows which satisfy two conditions or at least one of the two.
The following is a simplified query that gets the job done. Thing is, the where clause in my query is much more complex so I'm looking for a way to rewrite it in a more readable fashion.
Is this possible?
declare #AndParam bit
set #AndParam = 1
SELECT * FROM Table
Where
(#AndParam = 1
AND
(Table.CategoryID = 3
AND
Table.Age < 30))
OR
(#AndParam = 0
AND
(Table.CategoryID = 3
OR
Table.Age < 30))
EDIT:
This question really is about readability and esthetics.
In the stead of Table.Age < 30 there are five additional checks including subqueries. Practically, this means that I have a large section of the code duplicated with only one difference; The And/Or.
Seeing as how SQL can be difficult to read I'm looking to fix it up.
Maybe something like this:
Where
CASE WHEN Table.CategoryID = 3 THEN 1 ELSE 0 END +
CASE WHEN Table.Age < 30 THEN 1 ELSE 0 END -- + more CASEs for each condition
>=
CASE WHEN #AndParam = 1 THEN 2 ELSE 1 END
--For more conditions, change 2 above to however many conditions there are
You basically make each condition give you a 1 or 0, and then add all of these up - then you do a final check, depending on #AndParam on whether you hit the total number of conditions or just at least 1.