looking for a function - sql

I am new to SQL and I am trying to create a query that will give me the same result as LEFT OUTER JOIN but between two data bases. For example, in DB1 there are 100 records with the value X in specific column and in DB2 there 80 records. I want a query that will give the 20 missing records.
Thanks.

If you mean "between two tables":
select Table1.*
from Table1
left join Table2
on Table1.id = Table2.id
where Table2.id is null
This gives everything in Table2 that does not match
For more visual info on joins, go here
For basic info on SQL, try here

DB1 (table_users)
+----+-----------+--------------+
| id | username | lastname |
+----+-----------+--------------+
| 1 | xxxxxx | mmmmmmm |
+----+-----------+--------------+
| 2 | bbbbbb | wwwwwww |
+----+-----------+--------------+
DB2 (table_users)
+----+-----------+--------------+
| id | username | lastname |
+----+-----------+--------------+
| 1 | xxxxxx | mmmmmmm |
+----+-----------+--------------+
| 2 | bbbbbb | wwwwwwww |
+----+-----------+--------------+
| 3 | ccccc | ppppppppppp |
+----+-----------+--------------+
SELECT *
FROM DB2.table_users
WHERE phone_number NOT IN (SELECT * FROM DB2.table_users);
I think it servers the same purpose, except that your dealing with tables from different databases.

Related

How can I define IIf parameters across different records in a table?

I've defined a query that filters out records that are null in a specific field. I'd like to also calculate a query field that returns the type of record that follows the record that was filtered out, if it matches the parameters. The way I thought to do this was with an IIf statement with multiple parameters:
Preparing: IIf([tblCustomers!OrderId]=([tblCustomers!OrderId]+1)
AND [tblCustomers!OrderStatus]="Preparing","Preparing","")
This didn't work as I hoped, but I wasn't too surprised, as it would have to return data from the field initially tested. So, the argument that adds 1 is actually doing nothing.
Is there a way to target the next record in the table, test if it matches one of two or three strings, then return which one it is?
Edit: Following #mazoula's solution, it seems a correlated subquery is indeed the answer here. Following the guide on allenbrowne.com (linked by June7), I seemed to be on the right track. Here is my code for retrieving the status of a previous record:
SELECT tblCustomers.AccountId,
tblCustomers.OrderId,
tblCustomers.OrderStatus,
tblCustomers.OrderShipped,
tblCustomers.OrderNotes,
(SELECT TOP 1 Dupe.OrderStatus
FROM tblCustomers AS Dupe
WHERE Dupe.AccountId = tblCustomers.AccountId
AND Dupe.OrderId > tblCustomers.OrderId
ORDER BY Dupe.AccountId DESC, Dupe.OrderId) AS NextStatus
FROM tblCustomers
WHERE (((tblCustomers.OrderShipped)="N") AND
((tblCustomers.OrderNotes) Is Null))
ORDER BY tblCustomers.AccountId DESC;
Unfortunately, I am met with the following error:
At most one record can be returned by this subquery
Doing a little more research, I found that incorporating an INNER JOIN expression should solve this.
...
FROM tblCustomers
INNER JOIN OrderStatus Dupe ON Dupe.AccountId = tblCustomers.AccountId
WHERE ...
This is where I've hit another roadblock and, when the syntax is at least correct, I receive the error:
Join expression not supported.
Is this a simple syntax issue, or have misunderstood the role of a Join expression?
in Access 2016 I do this in two parts because access throws the error: must use an updateable query when I try to update based on a subquery. For instance, if I want to replace the Null Values in TableA.Field3 with 'a' if the next record's Field3 is 'a'
tableA:
-------------------------------------------------------------------------------------
| ID | Field1 | Field2 | Field3 |
-------------------------------------------------------------------------------------
| 1 | a | 1 | |
-------------------------------------------------------------------------------------
| 2 | b | 2 | |
-------------------------------------------------------------------------------------
| 3 | c | 3 | a |
-------------------------------------------------------------------------------------
| 4 | d | 4 | b |
-------------------------------------------------------------------------------------
| 5 | e | 5 | |
-------------------------------------------------------------------------------------
| 6 | f | 6 | b |
-------------------------------------------------------------------------------------
I make a table on which to base the update query:
Replacement: (SELECT TOP 1 Dupe.Field3 FROM [TableA] as Dupe WHERE Dupe.ID > [TableA].[ID])
'SQL PANE'
SELECT TableA.ID, TableA.Field1, TableA.Field2, TableA.Field3, (SELECT TOP 1 Dupe.Field3 FROM [TableA] as Dupe WHERE Dupe.ID > [TableA].[ID]) AS Replacement INTO TempTable
FROM TableA;
TempTable:
----------------------------------------------------------------------------------------------------------
| ID | Field1 | Field2 | Field3 | Replacement |
----------------------------------------------------------------------------------------------------------
| 1 | a | 1 | | |
----------------------------------------------------------------------------------------------------------
| 2 | b | 2 | | a |
----------------------------------------------------------------------------------------------------------
| 3 | c | 3 | a | b |
----------------------------------------------------------------------------------------------------------
| 4 | d | 4 | b | |
----------------------------------------------------------------------------------------------------------
| 5 | e | 5 | | b |
----------------------------------------------------------------------------------------------------------
| 6 | f | 6 | b | |
----------------------------------------------------------------------------------------------------------
Finally do the Update
UPDATE TempTable INNER JOIN TableA ON TempTable.ID = TableA.ID SET TableA.Field3 = [TempTable].[Replacement]
WHERE (((TempTable.Replacement)='a'));
TableA after update
-------------------------------------------------------------------------------------
| ID | Field1 | Field2 | Field3 |
-------------------------------------------------------------------------------------
| 1 | a | 1 | |
-------------------------------------------------------------------------------------
| 2 | b | 2 | a |
-------------------------------------------------------------------------------------
| 3 | c | 3 | a |
-------------------------------------------------------------------------------------
| 4 | d | 4 | b |
-------------------------------------------------------------------------------------
| 5 | e | 5 | |
-------------------------------------------------------------------------------------
| 6 | f | 6 | b |
notes: In the Make Table query remember to sort TableA and Dupe in the same way. Here we use the default sort of increasing ID for TableA then grab the first record with a higher ID using the default sort again. the only reason I did the filtering to 'a' in the update query is it made the Make Table query simpler.

Select two tables side by side

I have two tables filled with two files of which table1 always has one row more than the second.
I want to merge the two tables into one. When I use a right join e.g.
select *
from table2
right join table1 on table1.id = table2.id and table1.eq_nb = table2.eq_nb
I will have the 4 combinations for eq_nb = 25 because it is repeated two times.
But I rather want to stick the columns side by side
To know, I don't have conditions on arrival and depart time of each eq_nb (I can't add something like datediff(second,table1.arrival_time,table2.depart_time) < X )
table1:
id | eq_nb | arival_time
-------------------------------------
1 | 25 | 05:30:15.231
-------------------------------------
2 | 50 | 06:30:15.231
-------------------------------------
3 | 7 | 07:30:15.231
-------------------------------------
1 | 25 | 08:30:15.231
-------------------------------------
5 | 27 | 09:30:15.231
-------------------------------------
table2:
id | eq_nb | depart_time
----------------------------------
1 | 25 | 05:31:15.231
----------------------------------
2 | 50 | 06:31:15.231
----------------------------------
3 | 7 | 07:31:15.231
----------------------------------
1 | 25 | 08:31:15.231
----------------------------------
desired result:
id | eq_nb | arrival_time | depart_time
-------------------------------------------------------
1 | 25 | 05:30:15.231 | 05:31:15.231
-------------------------------------------------------
2 | 50 | 06:30:15.231 | 06:31:15.231
-------------------------------------------------------
3 | 7 | 07:30:15.231 | 07:31:15.231
-------------------------------------------------------
1 | 25 | 08:30:15.231 | 08:31:15.231
--------------------------------------------------------
5 | 27 | 09:30:15.231 | NULL
--------------------------------------------------------
left join should do what you want:
select *
from table1 t1 left join
table2 t2
on t1.id = t2.id and t1.eq_nb = t2.eq_nb;
Given your data, the ids are unique, so there should be no duplication. Note: This is equivalent to your first query; left join is typically easier to follow because all the rows in the first table are in the result set.
Here is a db<>fiddle, illustrating that it works.

Access Queries comparing two tables

I have two tables in Access, Table A and Table B:
Table MasterLockInsNew:
+----+-------+----------+
| ID | Value | Date |
+----+-------+----------+
| 1 | 123 | 12/02/13 |
| 2 | 1231 | 11/02/13 |
| 4 | 1265 | 16/02/13 |
+----+-------+----------+
Table InitialPolData:
+----+-------+----------+---+
| ID | Value | Date |Type
+----+-------+----------+---+
| 1 | 123 | 12/02/13 | x |
| 2 | 1231 | 11/02/13 | x |
| 3 | 1238 | 10/02/13 | y |
| 4 | 1265 | 16/02/13 | a |
| 7 | 7649 | 18/02/13 | z |
+----+-------+----------+---+
All I want are the rows from table B for IDs not contained in A. My current code looks like this:
SELECT Distinct InitialPolData.*
FROM InitialPolData
WHERE InitialPolData.ID NOT IN (SELECT Distinct InitialPolData.ID
from InitialPolData INNER JOIN
MasterLockInsNew
ON InitialPolData.ID=MasterLockInsNew.ID);
But whenever I run this in Access it crashes!! The tables are fairly large but I don't think this is the reason.
Can anyone help?
Thanks
or try a left outer join:
SELECT b.*
FROM InitialPolData b left outer join
MasterLockInsNew a on
b.id = a.id
where
a.id is null
Simple subquery will do.
select * from InitialPolData
where id not in (
select id from MasterLockInsNew
);
Try using NOT EXISTS:
SELECT Distinct i.*
FROM InitialPolData AS i
WHERE NOT EXISTS (SELECT 1
FROM MasterLockInsNew AS m
WHERE m.ID = i.ID)

how to get a Distinct Count of users from two related but different tables

Apologies for this but SQL is not a strong point for me, and whilst appears similar to lots of other queries I cannot translate those to this situation successfully.
I have two tables that will be related by a common value (id and Issue) if a row in table 2 exists.
I need to get a distinct count of users raising particular issues. I have users in both tables, with the table 2 user taking precedence if it exists.
There is always a REPORTER in Table 1, but there may not be a Stringvalue of Name (fieldtype = 1) in table 2. If there is a Stringvalue then that is the "User" and the Reporter can be ignored.
Table 1
| id | Reporter| Type |
| 1 | 111111 | 1 |
| 2 | 111111 | 2 |
| 3 | 222222 | 2 |
| 4 | 333333 | 1 |
| 5 | 111111 | 1 |
| 6 | 666666 | 1 |
Table 2
|issue | Stringvalue | fieldType|
| 1 | Fred | 1 |
| 1 | bananas | 2 |
| 2 | Jack | 1 |
| 5 | Steve | 1 |
I have a total of 4 issues of the right type (1,4,5,6), three reporters (111111,333333,666666) and two Stringvalues(Fred, Steve).
My total count of Distinct Users = 4 (Fred, 333333, Steve, 666666)
Result Table
| id| T1.Reporter | T2.Name |
| 1| Null | Fred |
| 4| 333333 | Null |
| 5| Null | Steve |
| 6| 666666 | Null |
How do I get this result in SQL!
Closest try so far:
SELECT
table1.REPORTER,
TO_CHAR(NULL) "NAME"
FROM table1
Where table1.TYPE =1
AND table1.REPORTER <> '111111'
Union
SELECT
TO_CHAR(NULL) "REPORTER",
table2.STRINGVALUE "NAME"
FROM table2,
table1
WHERE table2.ISSUE = table1.ID
AND table2.fieldtype= 1
and table1.issuetype = 1
Without explicitly excluding the default table 1 Reporter, this gets returned in my results even when there is a name value in table 2.
I have tried exists and in but cannot get syntax right or the correct results. As soon as try any Join that links the ID and Issue values the results always end up constrained to the matching rows or for all values. And added additional conditions to the ON does not return correct results.
I have tried too many permutations to list, logically this sounds like should be able to do union with where exists, or left outer join but my skills are lacking to make this work.
You need to use a LEFT JOIN and that is where you specify the fieldtype = 1 clause:
SELECT
table1.id,
CASE
WHEN table2.Stringvalue IS NOT NULL THEN table2.Stringvalue
ELSE table1.Reporter
END AS TheUser
FROM table1
LEFT JOIN table2 ON table1.id = table2.issue AND table2.fieldType = 1
WHERE table1.Type = 1
Result:
+------+---------+
| id | TheUser |
+------+---------+
| 1 | Fred |
| 4 | 333333 |
| 5 | Steve |
| 6 | 666666 |
+------+---------+
If I understand correctly, you want a left join and count(distinct). Here is what I think you are looking for:
select count(distinct coalesce(stringval, reporter) )
from table1 t1 left join
table2 t2
on t1.id = t2.issue and t2.fieldtype = 1
where t1.id in (1, 4, 5, 6);
You need to learn how to use explicit JOIN syntax. As a simple rule: Never use commas in the FROM clause. Always use explicit JOIN syntax. For one thing, it is more powerful, making it easy to express outer joins.

Multi-Table Selecting with Count of Foreign Key Referred Rows

I've tables related with foreign keys and i try to prepare a view to compose them via inner joins on SQL Server. I don't know if using inner join's is the way, but I can't get what I want anyway.
Tables are like below (I have more than 2 tables):
Table1:
| ID | Bla Bla... |
Table2:
| ID | Table1ID | Bla Bla... |
The query I tried is like this:
Select
Table1.ID, COUNT(Table2.ID) as FooCount
From
Table1
Inner Join
Table2 on Table2.Table1ID = Table1.ID
The result I want to see should be this:
| ID | FooCount |
-----------------------
| 1 | 45 |
| 2 | 75 |
| 3 | 98 |
| 4 | 100 |
| 5 | 11 |
| 6 | 37 |
How can I do this?
You don't even need a join to do this:
SELECT Table1Id AS ID, COUNT(*) as FooCount FROM Table2 GROUP BY Table1Id