I am new to SQL. I need to run a one-time query at a few different sites to get a count. The query needs to give me a count of all records based on a where clause. But I'm having trouble figuring out the syntax.
Here's what I tried:
SELECT COUNT(KEYS.IDXKEYID) FROM KEYS, KEYFLAGS
WHERE IDXLEVELID = 1
AND KEYFLAGS.BKEYSEVERMADE = -1
Which gave me a crazy number.
Basically, IDXKEYID is a primary key, and exists in both the KEYS and KEYFLAGS table. I want a count of all IDXKEYID records in the database that meet the above WHERE clause critera. I just want 1 simple result in 1 column/row.
COUNT
-----
12346
Thanks in advance!
SELECT COUNT(DISTINCT KEYS.IDXKEYID) -- count each key only once
FROM KEYS, KEYFLAGS
WHERE KEYS.IDXLEVELID = 1
AND KEYFLAGS.BKEYSEVERMADE = -1
AND KEYS.IDXKEYID = KEYFLAGS.IDXKEYID -- you're missing this link
Or you can write it using EXISTS
SELECT COUNT(1) -- count each key only once
FROM KEYS
WHERE KEYS.IDXLEVELID = 1
AND EXISTS (
SELECT *
FROM KEYFLAGS
WHERE KEYS.IDXKEYID = KEYFLAGS.IDXKEYID -- correlate
AND KEYFLAGS.BKEYSEVERMADE = -1)
Related
I'm having difficulties trying to return some data from a poorly structured one to many table.
I've been provided with a data export where everything from 'Section Codes' onwards (in cat_fullxPath) relates to a 'skillID' in my clients database.
The results previously returned on one line but I've used a split function to break these out (from the cat_fullXPath column). You can see the relevant 'skillID' from my clients DB in the far right column:
From here, there are thousands of records that may have a mixture of these skillIDs (and many others, I've just provided this one example). I want to be able to find the records that match all 4 (or however many match from another example) skillIDs and ONLY those.
For example (I just happen to know this ID gives me the results I want):
SELECT
id
skillID
FROM table1
WHERE skillID IN ( 1004464, 1006543, 1004605, 1006740 )
AND id = 69580;
This returns me:
Note that these are the only columns in that table.
So this is an ID I'd want to return.
These are results I'd not want to return as one of the skillIDs are missing:
I've created a temp table with a count of all the skills for each ID but I'm not sure if I'm going down the right path at this point
I'm pretty sure that there's a simple solution to this, however I'm hitting my head against the wall. Hope someone can help!
EDIT
This might be a clearer example of when there are different groups of skillIds that I need to align. I've partitioned these off by cat_fullxpath to see if this makes things clearer:
In this screenshot, for example I want to find the ids for everything in table1 where skillID IN (1003914,1005354,1004701) then repeat for (1004659,1004492,1004493,1004701). etc
We know that you need exactly 4 skills, so just make a subquery:
select id from
(
SELECT
id
count(skillID) countSkill
FROM table1
WHERE skillID IN ( 1004464, 1006543, 1004605, 1006740 )
group by id;
)
where countSkill = 4;
Could work with sum, instead of count. But instead of filtering by the 4, you filter by 4022352, which is the sum of all skillID.
You can also remove the subquery and use HAVING. But you will obtain worse performance.
SELECT
id
count(skillID) countSkill
FROM table1
WHERE skillID IN ( 1004464, 1006543, 1004605, 1006740 )
group by id
having count(skillID) = 4;
You haven't told us your DBMS. Here is a standard SQL approach:
select id
from table1
group by id
having count(case when skillid = 1004464 then 1 end) > 0
and count(case when skillid = 1006543 then 1 end) > 0
and count(case when skillid = 1004605 then 1 end) > 0
and count(case when skillid = 1006740 then 1 end) > 0
and count(case when skillid not in (1004464, 1006543, 1004605, 1006740) then 1 end) = 0;
Another option is to concatenate all skills and see if the resulting skill list matches the desired skill list. In SQL Server the string aggregation function is STRING_AGG.
select id
from table1
group by id
having string_agg(skillid, ',') within group (order by skillid) in
(
'1004464,1004605,1006543,1006740'
);
You can easily extend the IN clause with other combinations or even get the list from another table. Only make sure the skill IDs in the strings are sorted in order to make the strings comparable ('1004464,1004605,1006543,1006740' <> '1006740,1004464,1004605,1006543').
I have a table in the following format:
I feel like this should be simple but I'm struggling to come up with a performant query that can perform aggregations based on other rows with a shared key. For example, I want to sum the rows for a user with the key MediaLength but only if the rows with the key Score that share the event_id are greater than or equal to 3.
The result from a simple sum:
SELECT SUM(value::float) FROM data WHERE key = 'MediaLength' AND user_id = '9765f312-0d0b-4db0-b4c5-217eec81d7c3'
Result: 40
The result I am trying to achieve here is 15. In the table above you can see the rows are children of an event. I only want to sum the value column where key = 'MediaLength' and its sister row with key = 'Score' has value >= 3.
This is the query I have tried so far but it seems a bit messy and also doesn't work due to a more than one row returned by subquery error:
select
sum(value::float)
filter (where (
select d.value::float
from data d
where d.event_id = event_id
and d.key = 'Score'
) >= 3)
from data
where user_id = '9765f312-0d0b-4db0-b4c5-217eec81d7c3'
This is a simple example but in the future I would need to filter on potentially multiple other keys as well, so any advice on how to extend that is also hugely appreciated.
I only want to sum the value column where key = 'MediaLength' and its sister row with key = 'Score' has value >= 3.
SELECT sum(value::float) -- why the cast?
FROM data d
WHERE user_id = '9765f312-0d0b-4db0-b4c5-217eec81d7c3'
AND key = 'MediaLength'
AND EXISTS (
SELECT FROM data ds
WHERE ds.event_id = d.event_id
AND ds.user_id = d.user_id -- !
AND ds.key = 'Score'
AND ds.value >= 3
);
Here, rows with key = 'MediaLength' qualify if any sister passes the filter. (There may be more sisters failing the test.)
If there can only ever be a single qualifying sister row (enforced by a unique constraint / index?), a self-join is a bit simpler:
SELECT sum(value::float)
FROM data d
JOIN data ds USING (event_id, user_id)
WHERE d.user_id = '9765f312-0d0b-4db0-b4c5-217eec81d7c3'
AND d.key = 'MediaLength'
AND ds.key = 'Score'
AND ds.value >= 3;
The self-join would produce multiple result rows for multiple qualifying sister rows.
At its core, this can be cast as relational-division problem. Especially, since ...
in the future I would need to filter on potentially multiple other keys as well
See:
How to filter SQL results in a has-many-through relation
Good Day,
I have 3 Tables - Ticket, Ticket Batch (Multiple Ticket Rows To One Batch) and Ticket Staff (Multiple Staff Rows To One Ticket) and wish to ultimately UPDATE the ticket_batch table with the COUNT of all staff working on tickets per ticket batch.
The tables with applicable columns look as follows
ticket:
| ticket_number | recon_number |
ticket_batch:
| recon_number |
ticket_staff:
| ticket_number |
So I have written the following SQL query to essentially first if I do get the COUNT:
SELECT COUNT(*)
FROM ticket_staf
WHERE ticket_staff.ticket_number IN (SELECT GROUP_CONCAT(ticket.ticket_number) FROM ticket WHERE ticket.recon_number = 1);
Which the query just keeps running, but when I execute the queries separately:
SELECT GROUP_CONCAT(ticket.ticket_number)
FROM ticket
WHERE ticket.recon_number = 1;
I get 5 ticket numbers within split seconds and if I paste that string in the other portion of the query:
SELECT COUNT(*)
FROM ticket_staff
WHERE ticket_staff.ticket_number IN (1451,1453,1968,4457,4458);
It returns the correct COUNT.
So ultimately I guess can I not write queries with GROUP_CONCATS into another SELECT WHERE IN? And how should I structure my query?
Thanks for reading :)
I prefer Inner join as follows:
SELECT COUNT(distinct ts.*)
FROM ticket_staff ts
LEFT JOIN ticket t
ON ts.ticket_number = t.ticket_number
WHERE t.recon_number = 1;
GROUP_CONCAT() doesn't look right. I suspect you are confusing a list of values for IN with a string. They are not the same thing.
In general, I would recommend EXISTS over IN anyway:
SELECT COUNT(*)
FROM ticket_staff ts
WHERE EXISTS (SELECT 1
FROM ticket t
WHERE ts.ticket_number = t.ticket_number AND
t.recon_number = 1
);
For this query, you want an index on ticket(ticket_number, recon_number). However, I am guessing that ticket(ticket_number) is the primary key, which is enough of an index by itself.
I need to write an sql query that will pull back the data that meets several groups of criteria from the same table. The easiest way to describe is to imagine using an SQL "in" clause but instead of the internals of that clause being "or"s joining the parameters you want it to match it is instead an "and".
I attempted to use count to verify the correct amount of data was pulled back for each "in" statement but the count can't always be trusted due to other entries being similar for each column.
A sample table might be this:
id count animal
--- ----- ------
1 5 puppy
1 6 cat
1 6 puppy
So, now I need a query that will pull back all entries with an id of 1 and a count of 5 and 6 and an animal of puppy and cat. I pretty much need to verify the entire path of the table entry to know I want to pull it back. Is there any built in function that can do this? Do I need to use a recursive CTE to dig deep after confirming that one set of criteria is met? Thanks for any help.
If I got it right
with cnt as(
select id
from tbl
where [count] in (5,6) and animal in ('puppy', 'cat')
group by id
having count(distinct[count])=2 and count(distinct animal)=2
)
select id, [count], animal
from tbl
where id in (select id from cnt);
It's kind of confusing what you're looking for exactly but can you not use or's and ands?
select id, count, animal
from table
where id = 1 and
(count = 5 or count = 6) and
(animal = puppy or anmial = cat)
I think you just want:
select t.*
from t
where id = 1 and
count in (5, 6) and
animal in ('puppy', 'cat');
EDIT:
If you want them all in the same row, just rearrange the conditions:
select t.*
from t
where id = 1 and
( (count = 5 and animal = 'puppy') or
(count = 6 and animal = 'cat')
);
2 records in above image are from Db, in above table Constraint are (SID and LINE_ITEM_ID),
SID and LINE_ITEM_ID both column are used to find a unique record.
My issues :
I am looking for a query it should fetch the recored from DB depending on conditions
if i search for PART_NUMBER = 'PAU43-IMB-P6'
1. it should fetch one record from DB if search for PART_NUMBER = 'PAU43-IMB-P6', no mater to which SID that item belong to if there is only one recored either under SID =1 or SID = 2.
2. it should fetch one record which is under SID = 2 only, from DB on search for PART_NUMBER = 'PAU43-IMB-P6', if there are 2 items one in SID=1 and other in SID=2.
i am looking for a query which will search for a given part_number depending on Both SID 1 and 2, and it should return value under SID =2 and it can return value under SID=1 only if the there are no records under SID=2 (query has to withstand a load of Million record search).
Thank you
Select *
from Table
where SID||LINE_ITEM_ID = (
select Max(SID)||Max(LINE_ITEM_ID)
from table
where PART_NUMBER = 'PAU43-IMB-P6'
);
If I understand correctly, for each considered LINE_ITEM_ID you want to return only the one with the largest value for SID. This is a common requirement and, as with most things in SQL, can be written in many different ways; the best performing will depend on many factors, not least of which is the SQL product you are using.
Here's one possible approach:
SELECT DISTINCT * -- use a column list
FROM YourTable AS T1
INNER JOIN (
SELECT T2.LINE_ITEM_ID,
MAX(T2.SID) AS max_SID
FROM YourTable AS T2
GROUP
BY T2.LINE_ITEM_ID
) AS DT1 (LINE_ITEM_ID, max_SID)
ON T1.LINE_ITEM_ID = DT1.LINE_ITEM_ID
AND T1.SID = DT1.max_SID;
That said, I don't recall seeing one that relies on the UNION relational operator. You could easily rewrite the above using the INTERSECT relational operator but it would be more verbose.
Well in my case it worked something like this:
select LINE_ITEM_ID,SID,price_1,part_number from (
(select LINE_ITEM_ID,SID,price_1,part_number from Table where SID = 2)
UNION
(select LINE_ITEM_ID,SID,price_1,part_number from Table SID = 1 and line_item_id NOT IN (select LINE_ITEM_ID,SID,price_1,part_number from Table SID = 2)))
This query solved my issue..........