I'have a specific problem. I need get some some data from database. I have a mechanism to retrieve data from a program. I need to use it, no modifications possible. The original query is:
SELECT it_Symbol AS Symbol, tt_Name AS Nazwa, tt_Price AS Cena,
tt_Quantity AS Ilosc, tt_Id
FROM tr__Transaction INNER JOIN tr_Item
ON tt_TransId=tr_Id LEFT OUTER JOIN it__Item
ON tt_ItemId = it_Id RIGHT JOIN reg_Site
ON tr_SiteId = rs_Id LEFT OUTER JOIN it_ItemSite
ON it_Id = is_ItemId
WHERE tt_TransId=#transId
GROUP BY tt_Id, tt_Quantity, tr_Id, it_Name, tt_Price,it_Symbol,
is_Name, tt_Name, tt_ItemId, tt_Id
The problem is that I need to get some additional data from tr__Transaction table.
It has a field tr_Source. I need this fields value, but for tr__transaction records which have tr_Id listed in returned tt_Id field.
Any way to do a subquery returning values dependant on tt_Id column values?
Or maybe any other joins combination? I've spend whole week with this, and have no more ideas or skills to do this:/
Any help would be very appreciated.
Ok still don't know exactly what you need but it is an atempt to clean up the question. So this is a working version of the answer since you can't format code in comments.
Please explain if some relations are wrong.
you can always join tables multiple times under different conditions as long as they have different aliases.
For instance:
SELECT c.it_Symbol AS Symbol, a.tt_Name AS Nazwa, a.tt_Price AS Cena,
a.tt_Quantity AS Ilosc, a.tt_Id, f.tr_Source
FROM tr__Transaction a
INNER JOIN tr_Item b
ON a.tt_TransId=b.tr_Id
LEFT OUTER JOIN it__Item c
ON a.tt_ItemId = c.it_Id
RIGHT JOIN reg_Site d
ON a.tr_SiteId = d.rs_Id
LEFT OUTER JOIN it_ItemSite e
ON c.it_Id = e.is_ItemId
LEFT OUTER JOIN tr__Transaction f
ON c.tt_id = f.tr_id
WHERE a.tt_TransId=#transId
GROUP BY a.tt_Id, a.tt_Quantity, a.tr_Id, c.it_Name, a.tt_Price,c.it_Symbol,
e.is_Name, a.tt_Name, a.tt_ItemId, a.tt_Id
I'm not sure if I understand you question correctly, but assuming you are saying that the Original SQL statement cannot be changed (ie, it's in a read-only View). Then you can wrap it around another SELECT statement.
SELECT tblOriginal.*, tblExtend.tt_Source
FROM (
SELECT it_Symbol AS Symbol, tt_Name AS Nazwa, tt_Price AS Cena,
tt_Quantity AS Ilosc, tt_Id
FROM tr__Transaction INNER JOIN tr_Item
ON tt_TransId=tr_Id LEFT OUTER JOIN it__Item
ON tt_ItemId = it_Id RIGHT JOIN reg_Site
ON tr_SiteId = rs_Id LEFT OUTER JOIN it_ItemSite
ON it_Id = is_ItemId
WHERE tt_TransId=#transId
GROUP BY tt_Id, tt_Quantity, tr_Id, it_Name, tt_Price,it_Symbol,
is_Name, tt_Name, tt_ItemId, tt_Id
) AS tblOriginal
INNER JOIN tr__Transaction AS tblExtend
ON tblOriginal.tt_Id = tblExtend.tt_Id
But I suspect your problem is more complicated that that as you've spent over a week on it. In that case, can you elaborate?
Related
I know there ust be a few hundred of this similar post, but I have tried all the other ways in MS Access and still cannot get it to work.
So my working code is as follows
SELECT FVR.*, V.[Week Commencing], F.Date, V.Date
FROM FVR
INNER JOIN (F
INNER JOIN V ON (F.[Week Commencing] = V.[Week Commencing]) AND (F.GUID = V.GUID))
ON (FVR.GUID = V.GUID) AND (FVR.GUID = F.GUID)
My desired effect would be to show the Dates of the "F" table that have no entries in the "V"Table.
Sorry for being crpytic on the tables but it is for work. I thoght i had a good idead on how to do most of this.
any help would be amazing as I have been pulling my hair over this for a while now.
Cheers and thanks in advance.
Editing this to add in the full code as it will make more sense.
I basically have am unable to produce the Data range from F(Forecast) that Does not match in V(Visits) am trying to bring up a list of forecasted dates that have not been visited using the Week Commencing and GUID from both tables, The FVR table is just a table that holds the regional data matching up to the GUID. #Hogan I tried your way and ended up with syntax errors, I almost got somewhere and then lost it again. I thought I had a bit more knowledge of SQL than this.
Full code is as follows
SELECT FVR.*, [Visits].[Week Commencing], [Forecast].[Forecast Date], [Visits].Date
FROM ForecastVisitRegion
INNER JOIN ([Forecast] INNER JOIN [Visits] ON ([Forecast].[Week Commencing] = [Visits].[Week Commencing])
AND ([Forecast].GUID = [Visits].GUID)) ON (FVR.GUID = [Visits].GUID)
AND (FVR.GUID = [External - Forecast].GUID)
Thanks again
Stephen Edwards
You need to use left joins:
SELECT FVR.*, V.[Week Commencing], NZ(V.Date,F.Date) as virtual_date
FROM FVR
LEFT JOIN F ON FVR.GUID = F.GUID
LEFT JOIN V ON FVR.GUID = V.GUID F.[Week Commencing] = V.[Week Commencing]
Not sure I understand why FVR is coming into the mix but you need a left Join.
Select F.*
from F
left join V on F.[Week Commencing] = V.[Week Commencing] AND F.GUID = V.GUID
where V.GUID is null
The left join ensures all the records (matched or not) from F are included in the result set. Then the where V.GUID is null removes the records where no match was found in V leaving you with the F records with no match.
Another approach would be to use the NOT EXISTS statement in the WHERE Clause
Select F.*
from F
where not exists (select * from V where F.[Week Commencing] = V.[Week Commencing] AND F.GUID = V.GUID)
I am lost in my joins once again.
My count should be 4 instead of 16.
Can someone help me out? I can't find my problem on my own.
SELECT COUNT(TRK.REACTIE_ID) AS AANTAL_REACTIES,
AVG(W.WAARDERING) AS AANTAL_STERREN,
S.UITGEVER,
S.NAAM AS TVSHOW_NAAM,
S.BESCHRIJVING,
S.AFBEELDING_BESTANDSPAD,
S.ONDERTITEL,
S.WEBSITE,
C.NAAM AS CATEGORIE,
A.AFBEELDING_BESTANDSPAD,
A.VIDEO_BESTANDSPAD,
A.AFLEVERINGNR AS AFLEVERING,
A.SEIZOENNR AS SEIZOEN,
A.NAAM AS AFLEVERING_NAAM,
A.DUUR AS MINUTEN
FROM CATEGORIEEN_KOPPELTABEL CK
JOIN CATEGORIE C ON C.CATEGORIE_ID = CK.CATEGORIE_ID
JOIN TV_SHOW S ON S.TV_SHOW_ID = CK.TV_SHOW_ID AND S.NAAM = 'South Park'
LEFT JOIN TVSHOW_REACTIES_KOPPELTABEL TRK ON TRK.TV_SHOW_ID = S.TV_SHOW_ID
LEFT JOIN WAARDERING_TVSHOW W ON W.TV_SHOW_ID = S.TV_SHOW_ID
JOIN AFLEVERING A ON A.TV_SHOW_ID = S.TV_SHOW_ID
WHERE a.airdate = (SELECT MAX(TO_DATE(AIRDATE, 'DD:MM:YYYY'))
FROM AFLEVERING)
GROUP BY TRK.TV_SHOW_ID,
S.UITGEVER,
S.NAAM,
S.BESCHRIJVING,
S.AFBEELDING_BESTANDSPAD,
S.ONDERTITEL,S.WEBSITE,
C.NAAM,
A.AFBEELDING_BESTANDSPAD,
A.VIDEO_BESTANDSPAD,
A.AFLEVERINGNR,
A.SEIZOENNR,
A.NAAM,
A.DUUR,
W.TV_SHOW_ID;
RESULT OF THE QUERY
That is my result at the moment but there are 4 records of reactie.
"My count should be 4 instead of 16."
This indicates a missing JOIN condition or WHERE filter. This sort of thing can only be diagnosed by comparing the raw i.e. input data with the output and seeing which values appear too often. If you can't see this immediately, remove the aggregation and the group by clause, and perhaps add in some primary key columns.
One clue is that the aggregations are applied to values from the tables with outer joins:
LEFT JOIN TVSHOW_REACTIES_KOPPELTABEL TRK ON TRK.TV_SHOW_ID = S.TV_SHOW_ID
LEFT JOIN WAARDERING_TVSHOW W ON W.TV_SHOW_ID = S.TV_SHOW_ID
Outer joins can suck in rows we're not expecting, so you should check the logic you're trying to implement.
One other thing: don't mix filter conditions in the JOIN clause. The whole point of the ANSI 92 syntax is to keep them separate. So this ought to be in the WHERE clause:
AND S.NAAM = 'South Park'
It probably won't affect the actual result but occasionally it might.
I have encountered very strange behavior of my query and I wasted a lot of time to understand what causes it, in vane. So I am asking for your help.
SELECT count(*) FROM main_table
LEFT JOIN front_table ON front_table.pk = main_table.fk_front_table
LEFT JOIN info_table ON info_table.pk = front_table.fk_info_table
LEFT JOIN key_table ON key_table.pk = COALESCE(info_table.fk_key_table, front_table.fk_key_table_1, front_table.fk_key_table_2)
LEFT JOIN side_table ON side_table.fk_front_table = front_table.pk
WHERE side_table.pk = (SELECT MAX(pk) FROM side_table WHERE fk_front_table = front_table.pk)
OR side_table.pk IS NULL
Seems like a simple join query, with coalesce, I've used this technique before(not too many times) and it worked right.
In this query I don't ever get nulls for side_table.pk. If I remove coalesce or just don't use key_table, then the query returns rows with many null side_table.pk, but if I add coalesce join, I can't get those nulls.
It seems key_table and side_table don't have anything in common, but the result is so weird.
Also, when I don't use side_table and WHERE clause, the count(*) result with coalesce and without differs, but I can't see any pattern in rows missing, it seems random!
Real query:
SELECT ECHANGE.EXC_AUTO_KEY, STOCK_RESERVATIONS.STR_AUTO_KEY FROM EXCHANGE
LEFT JOIN WO_BOM ON WO_BOM.WOB_AUTO_KEY = EXCHANGE.WOB_AUTO_KEY
LEFT JOIN VIEW_WO_SUB ON VIEW_WO_SUB.WOO_AUTO_KEY = WO_BOM.WOO_AUTO_KEY
LEFT JOIN STOCK stock3 ON stock3.STM_AUTO_KEY = EXCHANGE.STM_AUTO_KEY
LEFT JOIN STOCK stock2 ON stock2.STM_AUTO_KEY = EXCHANGE.ORIG_STM
LEFT JOIN CONSIGNMENT_CODES con2 ON con2.CNC_AUTO_KEY = stock2.CNC_AUTO_KEY
LEFT JOIN CONSIGNMENT_CODES con3 ON con3.CNC_AUTO_KEY = stock3.CNC_AUTO_KEY
LEFT JOIN CI_UTL ON CI_UTL.CUT_AUTO_KEY = EXCHANGE.CUT_AUTO_KEY
LEFT JOIN PART_CONDITION_CODES pcc2 ON pcc2.PCC_AUTO_KEY = stock2.PCC_AUTO_KEY
LEFT JOIN PART_CONDITION_CODES pcc3 ON pcc3.PCC_AUTO_KEY = stock3.PCC_AUTO_KEY
LEFT JOIN STOCK_RESERVATIONS ON STOCK_RESERVATIONS.STM_AUTO_KEY = stock3.STM_AUTO_KEY
LEFT JOIN WAREHOUSE wh2 ON wh2.WHS_AUTO_KEY = stock2.WHS_ORIGINAL
LEFT JOIN SM_HISTORY ON (SM_HISTORY.STM_AUTO_KEY = EXCHANGE.ORIG_STM AND SM_HISTORY.WOB_REF = EXCHANGE.WOB_AUTO_KEY)
LEFT JOIN RC_DETAIL ON stock3.RCD_AUTO_KEY = RC_DETAIL.RCD_AUTO_KEY
LEFT JOIN RC_HEADER ON RC_HEADER.RCH_AUTO_KEY = RC_DETAIL.RCH_AUTO_KEY
LEFT JOIN WAREHOUSE wh3 ON wh3.WHS_AUTO_KEY = COALESCE(RC_DETAIL.WHS_AUTO_KEY, stock3.WHS_ORIGINAL, stock3.WHS_AUTO_KEY)
WHERE STOCK_RESERVATIONS.STR_AUTO_KEY = (SELECT MAX(STR_AUTO_KEY) FROM STOCK_RESERVATIONS WHERE STM_AUTO_KEY = stock3.STM_AUTO_KEY)
OR STOCK_RESERVATIONS.STR_AUTO_KEY IS NULL
Removing LEFT JOIN WAREHOUSE wh3 gives me about unique EXC_AUTO_KEY values with a lot of NULL STR_AUTO_KEY, while leaving this row removes all NULL STR_AUTO_KEY.
I recreated simple tables with numbers with the same structure and query works without any problems o.0
I have a feeling COALESCE is acting as a REQUIRED flag for the joined table, hence shooting the LEFT JOIN to become an INNER JOIN.
Try this:
SELECT COUNT(*)
FROM main_table
LEFT JOIN front_table ON front_table.pk = main_table.fk_front_table
LEFT JOIN info_table ON info_table.pk = front_table.fk_info_table
LEFT JOIN key_table ON key_table.pk = NVL(info_table.fk_key_table, NVL(front_table.fk_key_table_1, front_table.fk_key_table_2))
LEFT JOIN (SELECT fk_, MAX(pk) as pk FROM side_table GROUP BY fk_) st ON st.fk_ = front_table.pk
NVL might behave just the same though...
I undertood what was the problem (not entirely though): there is a LEFT JOIN VIEW_WO_SUB in original query, 3rd line. It causes this query to act in a weird way.
When I replaced the view with the other table which contained the information I needed, the query started returning right results.
Basically, with this view join, NVL, COALESCE or CASE join with combination of certain arguments did not work along with OR clause in WHERE subquery, all rest was fine. ALthough, I could get the query to work with this view join, by changing the order of joined tables, I had to place table participating in where subquery to the bottom.
I want to add the below join to the existing query. I am not aware whether the logic is correct.
Any help would be appreciated.
LEFT OUTER JOIN
dbo.note not
CASE
WHEN not.main_ref_type='M'
THEN pem.membership_id=not.main_ref_id
WHEN not.main_ref_type=P'
THEN per.person_id=not.main_ref_id
END
You need an on clause. It should look more like this:
LEFT OUTER JOIN
dbo.note not
on (not.main_ref_type='M' and not.main_ref_id = pem.membership_id) or
(not.main_ref_type='P' and per.person_id=not.main_ref_id)
You should know that joins with or conditions often perform badly. In many cases, it is better to do two separate joins (to the note table) and then use logic in the select (typically coalesce()) to get the right values.
Try this
LEFT OUTER JOIN dbo.note nt ON (nt.main_ref_type='M'
AND pem.membership_id=nt.main_ref_id)
OR
(nt.main_ref_type='P'
AND per.person_id=nt.main_ref_id)
END
CROSS APPLY (
VALUES
('M' , pem.membership_id),
('P' , per.person_id )
) map(ref_type, ref_id )
LEFT OUTER JOIN dbo.note not ON (
not.main_ref_type = map.ref_type AND
not.main_ref_id = map.ref_id
)
I posted a query yesterday (see here) that was horrible (took over a minute to run, resulting in 18,215 records):
SELECT DISTINCT
dbo.contacts_link_emails.Email, dbo.contacts.ContactID, dbo.contacts.First AS ContactFirstName, dbo.contacts.Last AS ContactLastName, dbo.contacts.InstitutionID,
dbo.institutionswithzipcodesadditional.CountyID, dbo.institutionswithzipcodesadditional.StateID, dbo.institutionswithzipcodesadditional.DistrictID
FROM
dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_3
INNER JOIN
dbo.contacts
INNER JOIN
dbo.contacts_link_emails
ON dbo.contacts.ContactID = dbo.contacts_link_emails.ContactID
ON contacts_def_jobfunctions_3.JobID = dbo.contacts.JobTitle
INNER JOIN
dbo.institutionswithzipcodesadditional
ON dbo.contacts.InstitutionID = dbo.institutionswithzipcodesadditional.InstitutionID
LEFT OUTER JOIN
dbo.contacts_def_jobfunctions
INNER JOIN
dbo.contacts_link_jobfunctions
ON dbo.contacts_def_jobfunctions.JobID = dbo.contacts_link_jobfunctions.JobID
ON dbo.contacts.ContactID = dbo.contacts_link_jobfunctions.ContactID
WHERE
(dbo.contacts.JobTitle IN
(SELECT JobID
FROM dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_1
WHERE (ParentJobID <> '1841')))
AND
(dbo.contacts_link_emails.Email NOT IN
(SELECT EmailAddress
FROM dbo.newsletterremovelist))
OR
(dbo.contacts_link_jobfunctions.JobID IN
(SELECT JobID
FROM dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_2
WHERE (ParentJobID <> '1841')))
AND
(dbo.contacts_link_emails.Email NOT IN
(SELECT EmailAddress
FROM dbo.newsletterremovelist AS newsletterremovelist))
ORDER BY EMAIL
With a lot of coaching and research, I've tuned it up to the following:
SELECT contacts.ContactID,
contacts.InstitutionID,
contacts.First,
contacts.Last,
institutionswithzipcodesadditional.CountyID,
institutionswithzipcodesadditional.StateID,
institutionswithzipcodesadditional.DistrictID
FROM contacts
INNER JOIN contacts_link_emails ON
contacts.ContactID = contacts_link_emails.ContactID
INNER JOIN institutionswithzipcodesadditional ON
contacts.InstitutionID = institutionswithzipcodesadditional.InstitutionID
WHERE
(contacts.ContactID IN
(SELECT contacts_2.ContactID
FROM contacts AS contacts_2
INNER JOIN contacts_link_emails AS contacts_link_emails_2 ON
contacts_2.ContactID = contacts_link_emails_2.ContactID
LEFT OUTER JOIN contacts_def_jobfunctions ON
contacts_2.JobTitle = contacts_def_jobfunctions.JobID
RIGHT OUTER JOIN newsletterremovelist ON
contacts_link_emails_2.Email = newsletterremovelist.EmailAddress
WHERE (contacts_def_jobfunctions.ParentJobID <> 1841)
GROUP BY contacts_2.ContactID
UNION
SELECT contacts_1.ContactID
FROM contacts_link_jobfunctions
INNER JOIN contacts_def_jobfunctions AS contacts_def_jobfunctions_1 ON
contacts_link_jobfunctions.JobID = contacts_def_jobfunctions_1.JobID
AND contacts_def_jobfunctions_1.ParentJobID <> 1841
INNER JOIN contacts AS contacts_1 ON
contacts_link_jobfunctions.ContactID = contacts_1.ContactID
INNER JOIN contacts_link_emails AS contacts_link_emails_1 ON
contacts_link_emails_1.ContactID = contacts_1.ContactID
LEFT OUTER JOIN newsletterremovelist AS newsletterremovelist_1 ON
contacts_link_emails_1.Email = newsletterremovelist_1.EmailAddress
GROUP BY contacts_1.ContactID))
While this query is now super fast (about 3 seconds), I've blown part of the logic somewhere - it only returns 14,863 rows (instead of the 18,215 rows that I believe is accurate).
The results seem near correct. I'm working to discover what data might be missing in the result set.
Can you please coach me through whatever I've done wrong here?
Thanks,
Russell Schutte
The main problem with your original query was that you had two extra joins just to introduce duplicates and then a DISTINCT to get rid of them.
Use this:
SELECT cle.Email,
c.ContactID,
c.First AS ContactFirstName,
c.Last AS ContactLastName,
c.InstitutionID,
izip.CountyID,
izip.StateID,
izip.DistrictID
FROM dbo.contacts c
INNER JOIN
dbo.institutionswithzipcodesadditional izip
ON izip.InstitutionID = c.InstitutionID
INNER JOIN
dbo.contacts_link_emails cle
ON cle.ContactID = c.ContactID
WHERE cle.Email NOT IN
(
SELECT EmailAddress
FROM dbo.newsletterremovelist
)
AND EXISTS
(
SELECT NULL
FROM dbo.contacts_def_jobfunctions cdj
WHERE cdj.JobId = c.JobTitle
AND cdj.ParentJobId <> '1841'
UNION ALL
SELECT NULL
FROM dbo.contacts_link_jobfunctions clj
JOIN dbo.contacts_def_jobfunctions cdj
ON cdj.JobID = clj.JobID
WHERE clj.ContactID = c.ContactID
AND cdj.ParentJobId <> '1841'
)
ORDER BY
email
Create the following indexes:
newsletterremovelist (EmailAddress)
contacts_link_jobfunctions (ContactID, JobID)
contacts_def_jobfunctions (JobID)
Do you get the same results when you do:
SELECT count(*)
FROM
dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_3
INNER JOIN
dbo.contacts
INNER JOIN
dbo.contacts_link_emails
ON dbo.contacts.ContactID = dbo.contacts_link_emails.ContactID
ON contacts_def_jobfunctions_3.JobID = dbo.contacts.JobTitle
SELECT COUNT(*)
FROM
contacts
INNER JOIN contacts_link_jobfunctions
ON contacts.ContactID = contacts_link_jobfunctions.ContactID
INNER JOIN contacts_link_emails
ON contacts.ContactID = contacts_link_emails.ContactID
If so keep adding each join conditon on until you don't get the same results and you will see where your mistake was. If all the joins are the same, then look at the where clauses. But I will be surprised if it isn't in the first join because the syntax you have orginally won't even work on SQL Server and it is pretty nonstandard SQL and may have been incorrect all along but no one knew.
Alternatively, pick a few of the records that are returned in the orginal but not the revised. Track them through the tables one at a time to see if you can find why the second query filters them out.
I'm not directly sure what is wrong, but when I run in to this situation, the first thing I do is start removing variables.
So, comment out the where clause. How many rows are returned?
If you get back the 11,604 rows then you've isolated the problems to the joins. Work though the joins, commenting each one out (remove the associated columns too) and figure out how many rows are eliminated.
As you do this, aim to find what is causing the desired rows to be eliminated. Once isolated, consider the join differences between the first query and the second query.
In looking at the first query, you could probably just modify that to eliminate any INs and instead do a EXISTS instead.
Consider your indexes as well. Any thing in the where or join clauses should probably be indexed.