MS Access - Outer Join ON condition not behaving - ms-access

I'm working with a query that does a simple outer join on 2 tables. Originally, the join is coded:
FROM [T1]
LEFT JOIN [T2]
ON [T1].[Bank Account #] = [T2].Account)
AND [T1].[Payment Reference] = [T2].[Reference #]
Simple enough. Until the "Reference" numbers started overlapping. Easiest solution is to code the join ONLY when the T1."payment dt" is <= T2."cashed date"
I have a ref# 222456 with a "cashed date" of 1/1/2011.
I have a new row w/ 222456 (different types, and numbers now overlapping. Type not available to match) with a payment date of 1/1/2016
To complicate matters, T1's Check date field is text, T2 is a date/time.
If I add this line:
and (Format(cDate([T1].[Payment Date]),'YYYYMMDD')
It DROPS the T1 row altogether.
I test the condition in the select, and it looks to be functioning as it should.
Where this condition is TRUE - I get appropriately matched T2 data
Where this condition is FALSE - and NO T2 record exists - I get just the T1 rec.
Where this condition is FALSE - but there is an existing T2 row where the first 2 fields match (but the date check fails) - then I get NO row returned at all.
I need T1 to return as if a T2 match is not found (which the ON should indicate)
Ideas?
Thanks!

Related

mysql: I want to sum up all the values of credit from table semester and then add to another column total_credit from another table

I have the below code:
UPDATE VIEW
LEFT JOIN sem_view ON (view.semester = sem_view.semester)
SET view.t_credit = SUM(sem_view.credit)
but its not working saying invalid use of group
Data for updating must be perpared previously, in subquery. Updating must use the data which is already aggregated.
Left joining may be errorneous - it will set the value in the destination table to NULL if according data for the semester in interest in sem_view is not present. But if the logic needs this then you may use LEFT JOIN instead of INNER one in the below query.
Totally:
UPDATE `view`
JOIN ( SELECT sem_view.semester, SUM(sem_view.credit) summ
FROM sem_view
GROUP BY sem_view.semester ) data_for_updating
ON `view`.semester = data_for_updating.semester
SET `view`.t_credit = data_for_updating.summ;
PS. The text looks like view is a name of a table to be updated.

SUBQUERY and INNER JOIN - differences between MySQL and SQL

This is a simple query I have used its like (using LIMIT 1 rather that TOP 1) various times in my own MySQL Database:
SELECT
j1.status AS "Status",
j1.number AS "Number",
(
SELECT TOP 1
i2.invoicedDate
FROM invoices AS i2
INNER JOIN jobs AS j2 ON i2.jobKey = j2.id
WHERE
j1.id=j2.id
AND
j2.status = 'INVOICED'
) AS "Invoiced Date"
FROM jobs AS j1
Lets say there are 183,000 rows in the om.jobGroup table, in MySQL the result would return all 183,000 results - and if nothing matched within the subquery it would return NULL
When I run the same query in a Microsoft SQL server; it not only takes significantly longer but only returns like 1700 records?
What is the best way to approach this from an SQL perspective - am I barking up the wrong tree?
Removing the sub query and doing a join on the main query still results in a missmatch of records.
Assuming the ids are unique, I think the query you want in either database is like this:
SELECT j1.status AS "Status", j1.number AS "Number",
(SELECT TOP 1 i2.invoicedDate
FROM invoices i2
WHERE i2.jobKey = j1.id AND j1.status = 'INVOICED'
) Invoiced_Date
FROM jobs j1;
Normally, TOP/LIMIT would be used with an ORDER BY.
Nothing in a subquery in the SELECT is going to change the number of rows.

MySQL - Use a placeholder for the value of a subquery where no rows are returned

This is basically the structure of my query:
SELECT * FROM foo WHERE foo1 = (subquery here)
I want to detect when the subquery doesn't return any rows, and then use another value as a placeholder.
How can I do that?
you can use left join, it will work :
SELECT * FROM table AS t1
left join
table as t2
on t1.Target = t2.Target
and t2.phase="B"
where t2.target is null OR
OR t1.date < t2.Date
you can replace your conditions here by changing null ans your conditions here.
By doing a left join you are including all rows on the left side of the join, and only matching rows from the right side of the join. Assuming a left side table t1, and right side table t2, in cases where the join condition is not met the value of any column in t2 will be be null. Since the goal in this case is to omit the where clause if our join condition is not met (targets match and the t2 phase value is 'B') we first check to see if the join condition failed, if so we return a row.
Got the answer!
SELECT * FROM foo WHERE foo1 = IF((subquery with count parameter as replacement), placeholder, (subquery))
Try your subquery alone , then use this:
mysql_num_rows to know how many rows has been affected by your subquery, if the number is 0 then create a query with another place holder
note
rowCount() to know the number of rows using PDO
you can just pass this by a condition above, like count your fetched data using using mysql_num_rwos , and assign that value to a variable and then put it in if else loop for conditions like as :
$a = mysql_num_rows(query);
if($a == '')
{
$a = your placeholder here;
}
SELECT * FROM foo WHERE foo1 ='".$a."'
something like that.

Issue with the TOP 1 query

Is it possible to achieve next thing without using views, but just one single query? I have two tables:
TableA->TanbleB (1-many) ON TableA.Id = TableB.TableAId
I need to update one field in Table A (TableA.Field1) for records in TableA that satisfy condition on one field in tableA (WHERE TableA.Field2=SomeValue)
.
TableA.Field1 will be updated from TableB with value that is last inserted (last inserted value in related records to TableA).
I will put an example:
UPDATE TableA a SET Field1 = (SELECT TOP 1 b.Feild1 * b.Field2 FROM TableB b WHERE b.TableAId = a.id) WHERE field2 = 1
I know Above example doesn't work, but I have many ways tried using INNER JOIN and failed. I had an idea to use something like this:
UPDATE TableA INNDER JOIN ( SELECT ... FROM TABLE B) ON TABLEA.Id= TableB.TableAId SET ....
But the 2ns query should return 1 record for each DISTINCT TableAId, but only the last inserted.
I hope I am making some sense here.
Thanks in advance.
Here is some SQL that will do what you want
UPDATE T1 INNER JOIN T2 ON T1.ID = T2.T1ID SET T1.F2 = [T2].[F2]*[T2].[F3] WHERE (((T1.F1)="ABC") AND ((T2.ID)=DMax("[ID]","[T2]","[T1ID]=" & [T1].[ID])));
This predicated on T1.ID being the primary key for T1 and T2.T1ID being a index field in T2
One of the flaws in Access is that you can't run an "UPDATE" query based on a "SELECT" query, it will usually give the error:
Operation must use an updateable query
The only way around is as you say to create a view of the "SELECT" query and then inner join this on your table, Access is then working with a static recordset and can handle the "UPDATE" query ok
Alternatively you could write a VBA procedure to step through line by line with the Recordset.
Best of luck : )
UPDATE:
SELECT b.TableAId, b.Feild1 * b.Field2 INTO tblView FROM TableB As b WHERE b.field2 = 1

Adding a column to a select statement based on the existence of a record in another table

I am writing a SQL query that I would like to add a column to the recordset which has a value based on the existence of a record in another table. I have a left join joining the tables, and I am assuming I have to do some sort of pivot in my SQL, but I am not familiar with table pivoting.
My existing SQL is
SELECT tabs.name,tabs.id AS tabid,tabs.sort,fields.id AS fieldid, fields.label
FROM tabs
INNER JOIN fields
ON tabs.id = fields.tabid
LEFT JOIN fields_reports
ON fields_reports.fieldid = fields.id
WHERE fields_reports.reportid = 57
GROUP BY fields.id
ORDER BY tabs.sort, fields.id
What happened in the SQL is that it pulls field (which is the core of the statement) and the tabs (which are essentailly categories). The fields_reports table maps fields to reports that I am building.
What I need to do is add a column to my statement that says: if the current field has a record in the fields_reports table with the report number passed in (57) then assign the column value of 1, else 0.
Edit: I have another issue with the query. Right now the query is only pulling fields attached to one report. Instead of using a case is there a way that I can do a subquery to select from the fields_reports table so that I can pull all fields and then have the column attaching it to a report?
This is the query that pulls the records now, but only pulls one reports fields
SELECT tabs.name,tabs.id AS tabid,tabs.sort,fields.id AS fieldid, fields.label,
CASE WHEN fields_reports.id IS null THEN 0 ELSE 1 END AS inReport
FROM fields
INNER JOIN tabs
ON tabs.id = fields.tabid
LEFT JOIN fields_reports
ON fields_reports.fieldid = fields.id
WHERE fields_reports.reportid = 57
GROUP BY fields.id
ORDER BY tabs.sort, fields.id
Let me know if I should open up a new question for this.
You can `SELECT ..., IF(field_reports.reportid=57),1,0), ... FROM ...`
EDIT The test on reportid in the WHERE clause will need to be removed, or else this makes little sense as a solution. (Thanks to #Dave Long for this.)
Look what I've done to your script:
SELECT tabs.name,tabs.id AS tabid,tabs.sort,fields.id AS fieldid, fields.label
FROM tabs
INNER JOIN fields
ON tabs.id = fields.tabid
LEFT JOIN fields_reports
ON fields.id = fields.id AND fields_reports.reportid = 57
GROUP BY fields.id
ORDER BY tabs.sort, fields.id
Noticed something different? I dropped the WHERE clause and moved the condition to the ON clause of LEFT JOIN fields_reports. WHERE, as it was specified, turned your LEFT JOIN into INNER JOIN, so the result set would only try to select the rows with fields_reports.reportid = 57. If there were no such rows, none would be returned, i.e. that way you couldn't have your flag column working.
But now it can be defined, for example, like this:
MAX(CASE fields_reports.reportid WHEN 57 THEN 1 ELSE 0 END) AS TheFlagColumn
Just append it to your select list.
The phrase would be:
select ....
, case when LeftJoinedTable.column is null then 0 else 1 end
from ....
this works because, when you left join and no row exists in the joined table, the columns are still present in the result but they are all null. So you can test for this null value to see if you matched to a row in the right side of the join.