ms access query - Filter out values from another query - sql

I've got a query running that pulls out the records I need.
I want to run another query that pulls out all the other records (excluding the ones in the first query).
I've read up on NOT IN and NOT LIKE but can't seem to get them to work.
The first query is named: qryHunnersPatients
Here's the code for the second query that I have so far:
Right now this is just pulling all the records - but I want to exclude those records in the qryHunnersPatients query
SELECT
tblPatientHistoryBaseline.ID,
tblPatientHistoryBaseline.Age,
[tblPatientHistoryBaseline].[Age]-[tblPatientHistoryBaseline].[UrinarySxBegan] AS Duration,
tblPatientHistoryBaseline.IBS,
tblQuestionnaires.UPOINTTotal,
tblQuestionnaires.U,
tblQuestionnaires.P,
tblQuestionnaires.O,
tblQuestionnaires.I,
tblQuestionnaires.N,
tblQuestionnaires.T,
tblQuestionnaires.ICSITotal,
tblQuestionnaires.ICPITotal
FROM
tblPatientHistoryBaseline
INNER JOIN
tblQuestionnaires
ON
(tblPatientHistoryBaseline.Visit = tblQuestionnaires.Visit)
AND
(tblPatientHistoryBaseline.ID = tblQuestionnaires.ID);
UPDATE:
I just tried the WHERE NOT EXISTS using the code below:
SELECT
tblPatientHistoryBaseline.ID,
tblPatientHistoryBaseline.Age,
[tblPatientHistoryBaseline].[Age]-[tblPatientHistoryBaseline].[UrinarySxBegan] AS Duration,
tblPatientHistoryBaseline.IBS,
tblQuestionnaires.UPOINTTotal,
tblQuestionnaires.U,
tblQuestionnaires.P,
tblQuestionnaires.O,
tblQuestionnaires.I,
tblQuestionnaires.N,
tblQuestionnaires.T,
tblQuestionnaires.ICSITotal,
tblQuestionnaires.ICPITotal
FROM
tblPatientHistoryBaseline
INNER JOIN
tblQuestionnaires
ON
(tblPatientHistoryBaseline.Visit = tblQuestionnaires.Visit)
AND
(tblPatientHistoryBaseline.ID = tblQuestionnaires.ID)
WHERE NOT EXISTS
(SELECT ID
FROM qryHunnersPatients AS hunners
WHERE hunners.ID = tblPatientHistoryBaseline.ID);

You need a SubQuery. As In understand that your Query qryHunnersPatients gives you the list of records that you do not wish to see, you need to include that in the NOT IN part of the Query.
SELECT
tblPatientHistoryBaseline.ID,
tblPatientHistoryBaseline.Age,
[tblPatientHistoryBaseline].[Age]-[tblPatientHistoryBaseline].[UrinarySxBegan] AS Duration,
tblPatientHistoryBaseline.IBS,
tblQuestionnaires.UPOINTTotal,
tblQuestionnaires.U,
tblQuestionnaires.P,
tblQuestionnaires.O,
tblQuestionnaires.I,
tblQuestionnaires.N,
tblQuestionnaires.T,
tblQuestionnaires.ICSITotal,
tblQuestionnaires.ICPITotal
FROM
tblPatientHistoryBaseline
INNER JOIN
tblQuestionnaires
ON
(tblPatientHistoryBaseline.Visit = tblQuestionnaires.Visit)
AND
(tblPatientHistoryBaseline.ID = tblQuestionnaires.ID)
WHERE
tblPatientHistoryBaseline.ID
NOT IN
(SELECT qryHunnersPatients.ID FROM qryHunnersPatients);

Assuming ID is unique, you can use WHERE NOT EXISTS:
SELECT {FieldList}
FROM tblPatientHistoryBaseline AS baseline
INNER JOIN tblQuestionnaires AS quest
ON (baseline.Visit = quest.Visit)
AND (baseline.ID = quest.ID);
WHERE NOT EXISTS (
SELECT ID
FROM qryHunnersPatients AS hunners
WHERE hunners.ID = baseline.ID
)
You don't need to bother using the aliases I've added to; I've just added them for readability.

Related

Connecting multiple queries and passing criteria from one query to another

I am trying to put together a query that will basically run another query on each return.
My current query puts together important info for each client, such as how long an average groom takes and the description of the type of haircut they get:
SELECT Query11.petId AS PetID,
Query11.petName AS PetName,
dbo_Customer.cstLName AS LastName,
Query11.lstValue AS Breed,
qryFindsPetAvgApptTime.TotalAppts,
dbo_vwPetGroom.pgrName AS GroomStyle,
dbo_ListValues.lstValue AS Haircut,
ROUND([AvgPTime]) AS AvgPrep,
ROUND([AvgBTime]) AS AvgBath,
ROUND([AvgDTime]) AS AvgDry,
ROUND([AvgGTime]) AS AvgGroom,
[AvgPrep] + [AvgBath] + [AvgDry] + [AvgGroom] AS AvgMinutes,
qryFindsPetAvgApptTime.AvgHours
FROM((Query11
LEFT JOIN qryFindsPetAvgApptTime ON Query11.petId = qryFindsPetAvgApptTime.PetID)
LEFT JOIN dbo_Customer ON Query11.petCustId = dbo_Customer.cstId)
LEFT JOIN (dbo_vwPetGroom
LEFT JOIN dbo_ListValues ON dbo_vwPetGroom.pgrLengthHairBodyLid = dbo_ListValues.lstId)
ON Query11.petId = dbo_vwPetGroom.pgrPetId;
I want to add in the average length between grooming appts to the above query info. Right now that is done in 2 seperate queries.
The first one pulls days between appts:
SELECT tblTimeLog.PetID,
tblTimeLog.PetName,
[ApptDate] - (SELECT MAX(T.ApptDate)
FROM tblTimeLog T
WHERE T.PetID = tblTimeLog.PetID
AND T.ApptDate < tblTimeLog.ApptDate) AS Diff,
tblTimeLog.ApptDate
FROM tblTimeLog
WHERE (((tblTimeLog.PetID) = [Enter PetID]))
ORDER BY tblTimeLog.ApptDate;
And then averaged out with this:
SELECT qryTimeLogDiffs.PetID,
qryTimeLogDiffs.PetName,
AVG(qryTimeLogDiffs.Diff) AS AvgOfDiff
FROM qryTimeLogDiffs
GROUP BY qryTimeLogDiffs.PetID,
qryTimeLogDiffs.PetName;
Is there a way to pass the PetID criteria from each return into the second query so it adds the average span between appts to the info in the first query??
Consider refactoring your second query to avoid the taxing correlated aggregate subquery. One approach involves first running an aggregate query based on a self join to return last appointment date for each PetID.
Even better, turn this query into an action query to populate a temporary table either with make-table query as shown below using INTO or regularly cleaning out a persistent table via delete and insert-select query:
SELECT curr.PetID,
curr.PetName,
curr.ApptDate,
MAX(prev.[AppDate]) AS MaxPrevDate
INTO lastApptTimeLog
FROM tblTimeLog AS curr
INNER JOIN tblTimeLog AS prev
ON curr.PetID = prev.PetID
WHERE prev.ApptDate < curr.AppDate
GROUP BY curr.PetID,
curr.PetName,
curr.ApptDate;
Then, base third aggregate query on this temp table and run the difference calculation. Finally, incorporate this query into first query.
SELECT PetID,
PetName,
AVG(ApptDate - MaxPrevDate) AS AvgOfDiff
FROM lastApptTimeLog
GROUP BY PetID,
PetName;

SQL SERVER 2008 - joins

I have three tables that I'm trying to join to get the necessary data. Here they are...
*TblComp* *TblCompParent* *tblCompProcesses*
CompID CompBillingID CompID
CompBillingID Capacity1 CompProcessID
Capacity2
So what I'm trying to do with these three tables is....
Select tblCompParent.Capacity1, tblCompParent.Capacity2, CompProcessID
My problem is this...In tblComp there are 351 values - so i start off by joining tblComp and tblCompparent and SELECTING tblCompparent.capacity1, tblcompparent.capacity2, the query looks like this...
SELECT dbo.tblComp.CompID, dbo.tblCompParents.Capacity1, dbo.tblCompParents.Capacity2
FROM dbo.tblCompParents INNER JOIN
dbo.tblComp ON dbo.tblCompParents.CompBillingID = dbo.tblComp.CompBillingID
And this works fine, it's when I try to join tblCompProcess to pull the CompProcessID is when I get like 580 records. I'm not sure what can of join I have to do on tblCompprocess to select only one CompProcessID per compID.
And it seems like i have to use tblComp otherwise I'll have no way of joining tblCompProcess.
EDIT1:
SELECT dbo.tblComp.CompID, dbo.tblCompParents.Capacity1, dbo.tblCompParents.Capacity2, tblCompProcess.compprocessID
FROM dbo.tblCompParents INNER JOIN
dbo.tblComp ON dbo.tblCompParents.CompBillingID = dbo.tblComp.CompBillingID
Inner Join dbo.tblCompprocess on tblCompProcess.CompID = tblComp.CompID
You don't show us the whole data model so I don't know exactly what is going on but clearly tblCompProcesses has more than one row in your join. I would fix it like this:
SELECT dbo.tblComp.CompID, dbo.tblCompParents.Capacity1, dbo.tblCompParents.Capacity2, x.compprocessID
FROM dbo.tblCompParents
INNER JOIN dbo.tblComp ON dbo.tblCompParents.CompBillingID = dbo.tblComp.CompBillingID
INNER JOIN (SELECT DISTINCT CompID, compprocessID
FROM dbo.tblCompprocess) X on x.CompID = tblComp.CompID

Select a field called "return" in postgreSQL

I'm having a problem with a query in postgres, the table cgporders_items has a field called return, I cannot get actual result of that field with this query, it returns me al ceros.
SELECT "Cgporder".id AS "Cgporder__id"
,"Sale".preorder_number AS "Sale__preorder_number"
,"Contact".id AS "Contact__id"
,"Contact".NAME AS "Contact__name"
,"Ptype".NAME AS "Ptype__name"
,(
SELECT code
FROM products
WHERE id = "CgporderItem".parent_id
) AS "Product__parent_code"
,"Product".id AS "Product__id"
,"Product".code AS "Product__code"
,"Product".NAME AS "Product__name"
,"CgporderItem".quantity AS "CgporderItem__quantity"
,"CgporderItem".return AS "CgporderItem__return"
,"CgporderItem".cep_id AS "CgporderItem__cep"
FROM cgporders AS "Cgporder"
INNER JOIN contacts AS "Contact" ON ("Contact".id = "Cgporder".contact_id)
INNER JOIN cgporders_items AS "CgporderItem" ON ("Cgporder".id = "CgporderItem".cgporder_id)
INNER JOIN products AS "Product" ON ("Product".id = "CgporderItem".product_id)
INNER JOIN ptypes AS "Ptype" ON ("Ptype".id = "Product".ptype_id)
LEFT JOIN cgporders_sales AS "CgporderSale" ON ("Cgporder".id = "CgporderSale".cgporder_id)
LEFT JOIN sales AS "Sale" ON ("Sale".id = "CgporderSale".sale_id)
WHERE "CgporderItem".parent_id != 0
AND "Cgporder"."issue_date" >= '2015-11-27'
AND "Cgporder"."issue_date" <= '2015-11-27'
AND "Cgporder"."status" = 'confirmed'
ORDER BY "Ptype".NAME
,"Product"."code";
There are actually a lots of rows that matches the select condition, but it return cero on "CgporderItem".return AS "CgporderItem__return"
If I make a simple query like select "return" from cgporders_items it works. But in this query it does not work.
Can you help me please?
"return" is a reserved word in SQL, but not in Postgres. See the list here. The following code works find in Postgres (SQL Fiddle is here):
create table dum (return int);
select dum.return from dum;
Your problem is something else. If I had to guess, the where clause is too restrictive (the condition on dates is a bit suspect).

Select Count of one table into another

I have one SQL statement as:
SELECT ARTICLES.NEWS_ARTCL_ID, ARTICLES.NEWS_ARTCL_TTL_DES,
ARTICLES.NEWS_ARTCL_CNTNT_T, ARTICLES.NEWS_ARTCL_PUB_DT,
ARTICLES.NEWS_ARTCL_AUTH_NM, ARTICLES.NEWS_ARTCL_URL, ARTICLES.MEDIA_URL,
ARTICLES.ARTCL_SRC_ID, SOURCES.ARTCL_SRC_NM, MEDIA.MEDIA_TYPE_DESCRIP
FROM
RSKLMOBILEB2E.NEWS_ARTICLE ARTICLES,
RSKLMOBILEB2E.MEDIA_TYPE MEDIA,
RSKLMOBILEB2E.ARTICLE_SOURCE SOURCES
WHERE ARTICLES.MEDIA_TYPE_IDENTIF = MEDIA.MEDIA_TYPE_IDENTIF
AND ARTICLES.ARTCL_SRC_ID = SOURCES.ARTCL_SRC_ID
AND ARTICLES.ARTCL_SRC_ID = 1
ORDER BY ARTICLES.NEWS_ARTCL_PUB_DT
Now I need to combine another SQL statement into one which is:
SELECT COUNT ( * )
FROM RSKLMOBILEB2E.NEWS_LIKES LIKES, RSKLMOBILEB2E.NEWS_ARTICLE ARTICLES
WHERE LIKES.NEWS_ARTCL_ID = ARTICLES.NEWS_ARTCL_ID
Basically I have one table which contains articles and I need to include the user likes which is in another table.
Use a subquery to add the likescount in your first query like this:
SELECT ARTICLES.NEWS_ARTCL_ID
,ARTICLES.NEWS_ARTCL_TTL_DES
,ARTICLES.NEWS_ARTCL_CNTNT_T
,ARTICLES.NEWS_ARTCL_PUB_DT
,ARTICLES.NEWS_ARTCL_AUTH_NM
,ARTICLES.NEWS_ARTCL_URL
,ARTICLES.MEDIA_URL
,ARTICLES.ARTCL_SRC_ID
,SOURCES.ARTCL_SRC_NM
,MEDIA.MEDIA_TYPE_DESCRIP
,(
SELECT COUNT(*)
FROM RSKLMOBILEB2E.NEWS_LIKES LIKES
WHERE LIKES.NEWS_ARTCL_ID = ARTICLES.NEWS_ARTCL_ID
) AS LikesCount
FROM RSKLMOBILEB2E.NEWS_ARTICLE ARTICLES
,RSKLMOBILEB2E.MEDIA_TYPE MEDIA
,RSKLMOBILEB2E.ARTICLE_SOURCE SOURCES
WHERE ARTICLES.MEDIA_TYPE_IDENTIF = MEDIA.MEDIA_TYPE_IDENTIF
AND ARTICLES.ARTCL_SRC_ID = SOURCES.ARTCL_SRC_ID
AND ARTICLES.ARTCL_SRC_ID = 1
ORDER BY ARTICLES.NEWS_ARTCL_PUB_DT;
I'm not sure what you are trying to achieve but it seems you want to count all the data from 2 tables. You can edit your query to something like this.
SELECT COUNT (ARTICLES.*) FROM RSKLMOBILEB2E.NEWS_LIKES LIKES
JOIN RSKLMOBILEB2E.NEWS_ARTICLE ARTICLES
ON LIKES.NEWS_ARTCL_ID = ARTICLES.NEWS_ARTCL_ID
I think that solution is in using Analytic Functions. Please have a look on https://oracle-base.com/articles/misc/analytic-functions
Please check following query (keep in mind I have no idea about your table structures). Due to left join records might be duplicated, this is why grouping is added.
SELECT ARTICLES.NEWS_ARTCL_ID, ARTICLES.NEWS_ARTCL_TTL_DES,
ARTICLES.NEWS_ARTCL_CNTNT_T, ARTICLES.NEWS_ARTCL_PUB_DT,
ARTICLES.NEWS_ARTCL_AUTH_NM, ARTICLES.NEWS_ARTCL_URL, ARTICLES.MEDIA_URL,
ARTICLES.ARTCL_SRC_ID, SOURCES.ARTCL_SRC_NM, MEDIA.MEDIA_TYPE_DESCRIP,
count(LIKES.ID) over ( partition by ARTICLES.NEWS_ARTCL_ID ) as num_likes
FROM RSKLMOBILEB2E.NEWS_ARTICLE ARTICLES
join RSKLMOBILEB2E.MEDIA_TYPE MEDIA
on ARTICLES.MEDIA_TYPE_IDENTIF = MEDIA.MEDIA_TYPE_IDENTIF
join RSKLMOBILEB2E.ARTICLE_SOURCE SOURCES
on ARTICLES.ARTCL_SRC_ID = SOURCES.ARTCL_SRC_ID
LEFT JOIN RSKLMOBILEB2E.NEWS_LIKES LIKES
ON LIKES.NEWS_ARTCL_ID = ARTICLES.NEWS_ARTCL_ID
WHERE
ARTICLES.ARTCL_SRC_ID = 1
group by ARTICLES.NEWS_ARTCL_ID, ARTICLES.NEWS_ARTCL_TTL_DES,
ARTICLES.NEWS_ARTCL_CNTNT_T, ARTICLES.NEWS_ARTCL_PUB_DT,
ARTICLES.NEWS_ARTCL_AUTH_NM, ARTICLES.NEWS_ARTCL_URL, ARTICLES.MEDIA_URL,
ARTICLES.ARTCL_SRC_ID, SOURCES.ARTCL_SRC_NM, MEDIA.MEDIA_TYPE_DESCRIP
ORDER BY ARTICLES.NEWS_ARTCL_PUB_DT
I also changed coma-separated list of tables from where condition to joins. I think this is more readable since table join conditions are separated from result filtering in where clause.

Timeout running SQL query

I'm trying to using the aggregation features of the django ORM to run a query on a MSSQL 2008R2 database, but I keep getting a timeout error. The query (generated by django) which fails is below. I've tried running it directs the SQL management studio and it works, but takes 3.5 min
It does look it's aggregating over a bunch of fields which it doesn't need to, but I wouldn't have though that should really cause it to take that long. The database isn't that big either, auth_user has 9 records, ticket_ticket has 1210, and ticket_watchers has 1876. Is there something I'm missing?
SELECT
[auth_user].[id],
[auth_user].[password],
[auth_user].[last_login],
[auth_user].[is_superuser],
[auth_user].[username],
[auth_user].[first_name],
[auth_user].[last_name],
[auth_user].[email],
[auth_user].[is_staff],
[auth_user].[is_active],
[auth_user].[date_joined],
COUNT([tickets_ticket].[id]) AS [tickets_captured__count],
COUNT(T3.[id]) AS [assigned_tickets__count],
COUNT([tickets_ticket_watchers].[ticket_id]) AS [tickets_watched__count]
FROM
[auth_user]
LEFT OUTER JOIN [tickets_ticket] ON ([auth_user].[id] = [tickets_ticket].[capturer_id])
LEFT OUTER JOIN [tickets_ticket] T3 ON ([auth_user].[id] = T3.[responsible_id])
LEFT OUTER JOIN [tickets_ticket_watchers] ON ([auth_user].[id] = [tickets_ticket_watchers].[user_id])
GROUP BY
[auth_user].[id],
[auth_user].[password],
[auth_user].[last_login],
[auth_user].[is_superuser],
[auth_user].[username],
[auth_user].[first_name],
[auth_user].[last_name],
[auth_user].[email],
[auth_user].[is_staff],
[auth_user].[is_active],
[auth_user].[date_joined]
HAVING
(COUNT([tickets_ticket].[id]) > 0 OR COUNT(T3.[id]) > 0 )
EDIT:
Here are the relevant indexes (excluding those not used in the query):
auth_user.id (PK)
auth_user.username (Unique)
tickets_ticket.id (PK)
tickets_ticket.capturer_id
tickets_ticket.responsible_id
tickets_ticket_watchers.id (PK)
tickets_ticket_watchers.user_id
tickets_ticket_watchers.ticket_id
EDIT 2:
After a bit of experimentation, I've found that the following query is the smallest that results in the slow execution:
SELECT
COUNT([tickets_ticket].[id]) AS [tickets_captured__count],
COUNT(T3.[id]) AS [assigned_tickets__count],
COUNT([tickets_ticket_watchers].[ticket_id]) AS [tickets_watched__count]
FROM
[auth_user]
LEFT OUTER JOIN [tickets_ticket] ON ([auth_user].[id] = [tickets_ticket].[capturer_id])
LEFT OUTER JOIN [tickets_ticket] T3 ON ([auth_user].[id] = T3.[responsible_id])
LEFT OUTER JOIN [tickets_ticket_watchers] ON ([auth_user].[id] = [tickets_ticket_watchers].[user_id])
GROUP BY
[auth_user].[id]
The weird thing is that if I comment out any two lines in the above, it runs in less that 1s, but it doesn't seem to matter which lines I remove (although obviously I can't remove a join without also removing the relevant SELECT line).
EDIT 3:
The python code which generated this is:
User.objects.annotate(
Count('tickets_captured'),
Count('assigned_tickets'),
Count('tickets_watched')
)
A look at the execution plan shows that SQL Server is first doing a cross-join on all the table, resulting in about 280 million rows, and 6Gb of data. I assume that this is where the problem lies, but why is it happening?
SQL Server is doing exactly what it was asked to do. Unfortunately, Django is not generating the right query for what you want. It looks like you need to count distinct, instead of just count: Django annotate() multiple times causes wrong answers
As for why the query works that way: The query says to join the four tables together. So say an author has 2 captured tickets, 3 assigned tickets, and 4 watched tickets, the join will return 2*3*4 tickets, one for each combination of tickets. The distinct part will remove all the duplicates.
what about this?
SELECT auth_user.*,
C1.tickets_captured__count
C2.assigned_tickets__count
C3.tickets_watched__count
FROM
auth_user
LEFT JOIN
( SELECT capturer_id, COUNT(*) AS tickets_captured__count
FROM tickets_ticket GROUP BY capturer_id ) AS C1 ON auth_user.id = C1.capturer_id
LEFT JOIN
( SELECT responsible_id, COUNT(*) AS assigned_tickets__count
FROM tickets_ticket GROUP BY responsible_id ) AS C2 ON auth_user.id = C2.responsible_id
LEFT JOIN
( SELECT user_id, COUNT(*) AS tickets_watched__count
FROM tickets_ticket_watchers GROUP BY user_id ) AS C3 ON auth_user.id = C3.user_id
WHERE C1.tickets_captured__count > 0 OR C2.assigned_tickets__count > 0
--WHERE C1.tickets_captured__count is not null OR C2.assigned_tickets__count is not null -- also works (I think with beter performance)