Create writeable multi table select query in Access - sql

I have two tables with below schema
Table 1 -
id, Serial Code, Hours
xxxx-aa, 1
xxxx-bb, 2
yyyy-aa, 1
Table 2 -
Stage , Description
aa, foo
bb, bar
Right now my joins are like this.
SELECT x.*, y.Description
FROM table1 x LEFT JOIN
table2 y
ON MID(serial, 6, 2) = y.stage
this gave me the desire result. however, it is readable only. I know I can create a writeable query if i separate out the foreign key in table 1 so the joining condition is
SELECT x.*, y.Description
FROM table1 x LEFT JOIN
table2 y
ON x.stage = y.stage
but is there a better way to create a writeable query without .. un-normalize.. table 1?
thanks.

One approach would be to create a calculated column called [stage] in table 1 and define it MID(serial,6,2). As you fill up the table, this column is automatically populated and allows you to query it simply as if you "un-normalized" table 1.

Related

SQL insert into table with values selected from other tables where an external value matches

I have the following tables:
Table1:
id
rarity
1
Common
2
Uncommon
3
Rare
Table2:
id
Type
1
Air
2
Earth
3
Fire
4
Water
The output table already exists and the schema is the following:
rarityID
weakness_typeID
resistance_typeID
and I should fill it with rows according to the Table2 and Table1.
For example if I'm given:
type is 'Water' and 'Air'
rarity is 'Common'
I'd like to add the IDs contained in Table1 and Table2 to this table to get the following updated output table:
rarityID
weakness_typeID
resistance_typeID
1
4
1
I've written the following query:
INSERT INTO table3 (rarityID, weakness_typeID, resistance_typeID)
SELECT rar.id, weak.id, res.id
FROM table1 rar, table2 weak, table2 res
WHERE rar.rarity = `Common`
AND weak.type = `Water`
AND res.type = `Air`;
But it doesn't work, can you help me?
My understanding of your problem is that you're trying to get ids for each of your information.
If this is correct, in order to do this you need to select their ids in three separate queries like it is done in the following query:
INSERT INTO table3 (rarityID, weakness_typeID, resistance_typeID)
SELECT (SELECT rar.id
FROM table1 rar
WHERE rar.rarity = 'Common') AS rarityID,
(SELECT weak.id
FROM table2 weak
WHERE weak.type = 'Water') AS weakness_typeID,
(SELECT weak.id
FROM table2 weak
WHERE weak.type = 'Air') AS resistance_typeID;
If you want to play with this code, check this SQL Fiddle.

How to prove that ALL records from Query A are present in Table B for millions of records?

I have query written (in Microsoft SQL Server Management Studio V18) which does multiple inner joins to give result set with 3 columns: ZipCode, ID, Income.
This result set contains 118 Million records
I have Table B with 2 columns: ZipCode, ID
Table B contains 123 Million records
These 118M records are present in Table B and I want to prove that.
How do I do this? I don't want another resultset that will display all these 118M records on the output console.
I can add first result set in a temp table but I am stuck after that.
Ideally I would like to see something printed on the console that will say that "All the records from temp table are present in target table<Table_Name>"
If not, what could be an ideal way to prove that all these records are present in target table?
so after say you have pushed your query results into temp table say #a, we can proceed like below
IF NOT EXISTS
(
SELECT TOP 1 1
FROM #a A
WHERE NOT EXISTS
(
SELECT 1 FROM TableB B
ON A.ZipCode=B.ZipCode
AND A.Id= B.ID
)
)
BEGIN
PRINT 'All the records from temp table are present in target table<Table_Name>'
END
WITH
TA AS (SELECT ...), --> first query
TB AS (SELECT ...) --> second query
SELECT * FROM TA
EXCEPT
SELECT * FROM TB
UNION ALL
SELECT * FROM TB
EXCEPT
SELECT * FROM TA;
Then replace by your queries TA and TB.

Exclude one item with different corelated value in the next column SQL

I have two tables:
acc_num
ser_code
1
A
1
B
1
C
2
C
2
D
and the second one is:
ser_code
value
A
5
B
8
C
10
D
15
I want to exclude all the accounts with the service codes that they have value of 10 or 15.
Because my data set is huge, I want to use NOT EXIST but it just excludes combination of acc_num and ser_code.
I want to exclude the acc_num with all of it's ser_code, because on of it's ser_code meats my criteria.
I used:
select acc_num, ser_code
from table 1
where NOT EXIST (select 1
FROM table 2 where acc_num = acc_num and value in (10, 15)
out put with above code is:
acc_num
ser_code
1
A
1
B
Desire out put would be empty.
here you are
select t1.acc_num,t1.ser_code from table1 t1, table2 t2
where (t1.ser_code=t2.ser_code and t2.value not in (10,15))
and t1.acc_num not in
(
select t3.acc_num from table1 t3,table2 t4
where t1.acc_num=t3.acc_num and t3.ser_code=t4.ser_code
and t4.value in (10,15)
) ;
This could be achieved in many ways. However using NOT EXISTS is the best option. The problem with your query is for acc_num 1, there are ser_code that does not have value as 10, 15. So you will get A and B in result.
To overcome that you must pull acc_num inside the sub-query
Query 1 (using NOT EXISTS):
As you can see in the below query, I have included acc_num inside sub-query, so that the filter works properly,
SELECT DISTINCT a.acc_num, a.ser_code
FROM one as a
WHERE NOT EXISTS
(
SELECT DISTINCT one.acc_num
FROM two
INNER JOIN one
ON one.ser_code=two.ser_code
WHERE value IN (10,15) AND a.acc_num=one.acc_num
)
Query 2 (using LEFT JOIN):
NOT EXISTS often confusing due to it's nature (super fast though). Hence LEFT JOIN could also be used (expensive than NOT EXISTS),
SELECT DISTINCT a.acc_num, a.ser_code
FROM one as a
LEFT JOIN
(
SELECT DISTINCT one.acc_num
FROM two
INNER JOIN one
ON one.ser_code=two.ser_code
WHERE value IN (10,15)
) b
ON a.acc_num=b.acc_num
WHERE b.acc_num IS NULL
Query 3 (using NOT IN):
NOT IN would also achieve this with comprehensive query but expensive than both of the above methods,
SELECT DISTINCT a.acc_num, a.ser_code
FROM one as a
WHERE a.acc_num NOT IN
(
SELECT DISTINCT one.acc_num
FROM two
INNER JOIN one
ON one.ser_code=two.ser_code
WHERE value IN (10,15)
)
All 3 would yield same result. I would prefer to go with NOT EXISTS
See demo with time consumption in db<>fiddle

select rows first that has a match id in a temporary table

I have a temporary table that contains a list of id's and what I want is when I query from my main table those id's that is in my temporary table will be shown first in the result.
Example:
This is the data from temporary table:
ID
--
7
5
3
Then when I query in my main table I want the ID's from the temporary table to show first in my result.
ID
--
7 -- from temp table
5 -- from temp table
3 -- from temp table
1
2
4
6
Is that possible?
A simple left join should behave the way you want:
SELECT m.*
FROM main_table m
LEFT JOIN temp_table t
ON m.id = t.id
ORDER BY
t.id DESC;
The ORDER BY clause I used should work, and those records in the main_table which did not match to anything in the temp_table should be pushed to the bottom of the result set. You could also add another level of sorting if you wanted to.

matching value by non-unique id and minimum date difference

I'm using sqlite through the RSQLite package in R.
I have two tables:
Table 1 has important columns 'PERMCO' and 'Reporting_Period'.
('Reporting_Period' is an integer date)
Table 2 has important columns 'PERMCO' and 'date'.
('date' is an integer date)
I want to do a left join with table 1 as the left table.
Thing is that 'PERMCO' is not unique (row-wise, many duplicates) in the second table.
For a given row of table 1, I want the match from the second table to be the row from table 2 with matching PERMCO that is closest in absolute date to 'Reporting_Period' in the first table.
Not really sure how to do this...
Thank you
The Idea is a correlated subquery to get the closest day in table2 from Reporting_Period in table1
SELECT t1.*, t2.*
FROM table1 t1
LEFT JOIN table2 t2
ON t1.permco = t2.permco
WHERE ABS(t2."date" - t1.Reporting_Period) = (SELECT MIN(ABS("date" - t1.Reporting_Period) )
FROM table2
WHERE permco = t1.permco
)
OR t2.permco IS NULL --because you want a left join
;
I'm not familier with Sqlite, so you may need to change the query to subtract the two date.