Stuck on a slightly tricky query, trying to ignore multiple results based on a single field - sql

Here is a simple database representation of what I'm stuck on:
IDNumber TimeSpent Completed
1 0 No
1 0 No
1 2 No
2 0 No
3 0 No
I'm currently querying the database as such...
"SELECT Distinct (IDNumber) AS Info FROM TestTable
ORDER BY WorkOrderNumber";
And it gives me back the results
1
2
3
Which is expected.
Now, I'd like to adjust it to where any instance of an IDNumber that have TimeSpent != 0 or Completed != No means that the IDNumber isn't grabbed at all. So for example in the database given, since TimeSpent = 2, I don't want IDNumber 1 to be returned in my query at all.
My first instinct was to jump to something like this...
"SELECT Distinct (IDNumber) AS Info FROM TestTable
WHERE TimeSpent='0' AND Completed='No'
ORDER BY WorkOrderNumber";
But obviously that wouldn't work. It would correctly ignore one of the IDNumber 1's but since two others still satisfy the WHERE clause it would still return 1.
Any pointers here?

SELECT DISTINCT IDNumber
FROM TestTable
WHERE IDNumber NOT IN
(SELECT IDNUmber FROM TestTable WHERE TimeSPent <> 0 OR Completed <> 'No')

You can do this with an aggregation, using a having clause:
select IDNumber
from TestTable
group by IDNumber
having sum(case when TimeSpent = 0 then 1 else 0 end) = 0 and
sum(case when Completed = 'No' then 1 else 0 end) = 0
The having clause is counting the number of rows that meet each condition. The = 0 is simply saying that there are no matches.
I prefer the aggregation method because it is more flexible in terms of the conditions that you can set on the groups.

Related

I'm trying to take a record from, for example row 1 and insert it into row 3

I have a field called RecordType that has three different records, 1, 2, 3. Each hold different records. I want to take the the balance from another field I have called Limit from RecordType 1 and insert it into RecordType 3 but I'm just unsure on how to do this. This will be going into a Crystal Report and I want to be able to suppress the RecordType 1 altogether.
I've tried a simple case statement but that's about it, I can't really think of any other ways to do it (I'm sure there's loads).
CASE
WHEN FA.RecordType = 3 THEN
FA.Limit
END AS LimitTest
Current results
Record Type
Limit
1
5,000,301
2
0
3
0
Expected Results
Record Type
Limit
2
0
3
5,000,301
You seem to want to combine the limit for types 1 and 3. You can do this with aggregation on an expression:
select (case when recordtype = 1 then 3 else recordtype end) as recordtype,
sum(limit) as limit
from t
group by (case when recordtype = 1 then 3 else recordtype end);
You can try using sub-query and a Case statement in your select statement, for example:
SELECT [RecordType],
(CASE [RECORDTYPE] WHEN 3 THEN
(SELECT LIMIT from Table_1 WHERE RECORDTYPE = 1)
ELSE LIMIT END) LimitTest
FROM TABLE_1 WHERE RECORDTYPE <> 1
You said:
Sorry my formatting is terrible I'm not sure how to do it properly. But to answer your question no type 1 & 3 will never have the same value as 3 never has a value. I want to basically move the value from type 1 into type 3
Which makes me think that this would be the simplest:
DELETE FROM table WHERE RecordType = 3
UPDATE table SET RecordType = 3 WHERE RecordType = 1
3 never has a value so let's get rid of them first, then 1 has the value but we want it to be 3 so just update all the 1s to be 3s instead
If you're not into deleting it, just mask it instead:
SELECT 3 as RecordType, Limit FROM table WHERE RecordType = 1
If you want to move value from type 1 to type 3 then do simple update in your query.
update t set t.value= t1.value from table as t , table as t1 where t.recordtype=3 and t1.recordtype=1
or
delete from table where recordtype = 3
update recordtype set recordtype=1 where recordtype=3
This will work may be
SELECT
IIF(A.RECORDTYPE = 1,3,A.RECORDTYPE) AS RECORDTYPE,
A.LIMIT
FROM
(
SELECT 1 RECORDTYPE,5000301 LIMIT UNION ALL
SELECT 2 RECORDTYPE,0 LIMIT UNION ALL
SELECT 3 RECORDTYPE,0 LIMIT
) A
WHERE A.RECORDTYPE IN (1,2)
ORDER BY RECORDTYPE
Check this if works for you.

GROUP BY with COUNT condition

I have a result set such as:
Code No
1 *
1 -
1 4
1
1
Now i basically want a query that has 2 columns, a count for the total amount and a count for those that dont have numbers.
Code No_Number Total
1 4 5
Im assuming this needs a group by and a count but how can i do the 2 different counts in a query like this?
This is what i had so far, but i am a bit stuck with the rest of it
SELECT CODE,NO
Sum(Case when No IN ('*', '-', '') then 1 else 0 end) as Count
I think you basically just need GROUP BY:
SELECT CODE,
SUM(Case when No IN ('*', '-', '') then 1 else 0 end) as Count,
COUNT(*) as total
FROM t
GROUP BY CODE;
Well, this took a moment :-), however here it is...I have used a CASE statement to create and populate the No_Number column; the database gives the row in the original table a value of 1 if the original table value is a number or gives it a NULL and discards it from the COUNT if not. Then when it makes the count it is only recognising values which were originally numbers and ignoring everything else..
If the result set is in a table or temp table:
SELECT Code,
COUNT(CASE WHEN [No] NOT LIKE '[0-9]' THEN 1 ELSE NULL END) AS No_Number,
COUNT(Code) AS Total
FROM <tablename>
GROUP BY Code
If the result set is the product of a previous query you can use a CTE (Common Table Expression) to arrive at the required result or you could include parts of this code in the earlier query.

Impala SQL, return value if a string exists within a subset of values

I have a table where the id field (not a primary key) contains either 1 or null. Over the past several years, any given part could have been entered multiple times with one, or both of these possible options.
I'm trying to write a statement that will return some value if there is ever a 1 associated with the select statement. There are lots of semi-duplicate rows, some with 1 and some with null, but if there is ever a 1, I want to return true, and if there are only null values, I want to return false. I'm not sure how to code this though.
If this is my SELECT part,id from table where part = "ABC1234" statement
part id
ABC1234 1
ABC1234 null
ABC1234 null
ABC1234 null
ABC1234 1
I want to write a statement that returns true, because 1 exists in at least one of these rows.
The closest I've come to this is by using a CASE statement, but I'm not quite there yet:
SELECT
a1.part part,
CASE WHEN a2.id is not null
THEN
'true'
ELSE
'false'
END AS id
from table.parts a1, table.ids a2 where a1.part = "ABC1234" and a1.key = a2.key;
I also tried the following case:
CASE WHEN exists
(SELECT id from table.ids where id = 1)
THEN
but I got the error subqueries are not supported in the select list
For the above SELECT statement, how do I return 1 single line that reads:
part id
ABC1234 true
You can use conditional aggregation to check if a part has atleast one row with id=1.
SELECT part,'True' id
from parts
group by part
having count(case when id = 1 then 1 end) >= 1
To return false when the id's are all nulls use
select part, case when id_true>=1 then 'True'
when id_false>=1 and id_true=0 then 'False' end id
from (
SELECT part,
count(case when id = 1 then 1 end) id_true,
count(case when id is null then 1 end) id_false,
from parts
group by part) t

Aggregate sub-query not producing expected results

I have two tables and there's a one to many relationship between the two. My query has a group by and I want to determine if there are any results in the 2nd table that match some criteria. I couldn't figure it out with a sub-query and tried the following code, but it's not giving you the results you expect.
CASE WHEN
(SELECT SUM(CASE WHEN a.ContentId IS NULL THEN 1 ELSE 0 END)) > 0
THEN 1
ELSE 0
END as 'HasAttachments'
Basically, I am trying to figure out if my message (which could have many attachments) has any attachments where the ContentId is null and if that count is greater than 0 then I want to return the boolean value in HasAttachments.
Any help would be great!
CASE WHEN
SUM(CASE WHEN a.ContentId IS NULL
AND a.message_id IS NOT NULL
THEN 1
ELSE 0
END) > 0
THEN 1
ELSE 0
END as HasAttachments
From your narratives it seems like your inner Case Statement is missing another condition to determine when there is actually an attachment. If you don't put in the second condition of when the AttachmentTable.message_id IS NOT NULL then you will count both messages that don't have any attachments and those messages that have attachments but no content id as the same thing. But adding the a.message_id you limit that to just the case you seem to desire from your narrative.
Here is one way I might phrase the query:
select m.*,
(case when exists (select 1 from attachments a where a.message_id = m.message_id and content_id is null
)
then 1 else 0
end) as HasAttachments
from messages m;
It is unclear why your query doesn't work, without the context of the rest of the query.

SQL - Counting a column twice

I have a table that has a column called 'status'. This can be set to 0 or 1
Is it possible for me to count both the 0's and 1's in a single query?
Thanks in advance
James
Yes, just group on the value of status:
SELECT status, COUNT(*)
FROM yourtable
GROUP BY status
That will give you exactly two rows since the value can only be 0 or 1, and the COUNT(*) column will be the number of times each status value appears in the table.
SELECT SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) AS 'number of zeroes',
SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS 'number of ones'
FROM yourtable;