Joining two tables, one of which containing the other - sql

I am new in the SQL world (my problem might be very easy to solve).
Also,I work exclusively on Access.
I'm french and I realise that it is hard for me to explain so I'll give you a demo after.
I have two tables, A and B.
Both have a column id and all of the id of B are in A (but B has different columns however)
I'd like to join them, based on the id of course, to obtain a table containing A plus B when there is a matching id.
Therefore result must have the exact number of rows as table A.
Table A
id - value1 - value2
1 0.5 0.6
2 0.4 0.9
3 0.4 1
4 0.8 1
Table B
id - name1 - name2
1 az at
4 df ml
Result:
id- value1- value2 - name1- name2
1 0.5 0.6 az at
2 0.4 0.9
3 0.4 1
4 0.8 1 df ml
When an element of A is not in B, I still need to have them in the result, with a null value in the columns where the information is missing.
If you don't understand my english, just look at the demo, it's self explanatory
I tried to code a FULL OUTER JOIN by myself (because it doesn't exist in Access) but the result I get is a table with a lot of duplicates.
I also tried a lot of JOINs but I always get a table with a lot more rows than A
Thanks in advance :)

I think you just need a left join here:
SELECT
a.id,
a.value1,
a.value2,
b.name1,
b.name2
FROM TableA a
LEFT JOIN TableB b
ON a.id = b.id;
A left join would guarantee that every row in TableA would appear in the result set, even if a given row's id value did not match to anything in TableB.
If you don't want NULL to possibly appear for the name1 and name2 fields for those records where there was no match, then consider using Nz(name1, '') to show empty string instead.

Related

Getting ranges of arbitrary strings in SQL based on sequence dictated in a separate table

Consider the following dataset (may look weird but want to land my point that the strings are arbitrary):
Table A
TicketId
StartAnimal
EndAnimal
1
Monkey
Bee
1
Lion
Buffalo
Table B
Animal
Sequence
Monkey
1
Zebra
2
Bee
3
Turtle
4
Lion
5
Buffalo
6
Is it possible to retrieve the animals that correspond to Ticket ID 1 based on the different "ranges" in each of its rows? For example,for Ticket ID 1 the following animals should be retrieved: Monkey, Zebra, Bee, Lion, Buffalo.
As you can see the animal strings themselves have no order logic to it, but the sequence can be leveraged for it. I'm just failing to come up with how to reference it for each row in a single query.
Edit
As an edge case, sometimes the EndAnimal might not even have a sequence to start with, in which case only the StartAnimal should be returned. As an example, assuming Bee is not in the sequence table, we should only get Monkey, Lion and Buffalo. Is that something SQL can handle?
Thanks!
There are numerous ways, one such way is to inner join the tables to find the corresponding start and end sequences and then find those rows that qualify:
with s as (
select bs.Sequence s1, IsNull(be.sequence,1) s2, a.ticketId
from a left join b bs on bs.animal = a.StartAnimal
left join b be on be.Animal = a.EndAnimal
)
select b.Animal
from b
join s on b.Sequence >=s1 and b.Sequence <= s2
where s.ticketId = 1
order by b.Sequence;
Example Fiddle

How to merge two tables with a different amount and order of columns in SSMS?

I have one large table with ~10,000 rows of data and 100 columns that I want to continuously update. The problem is that the files I will use to update (.csv) often are in different orders or contain extra/missing columns. If there are extra columns in the update I am fine discarding them, but I want the remaining columns to match up exactly, even if some are missing or out of order.
I know that there is a solution in creating a select and simply listing all columns, but I am looking for something more elegant/foolproof. Many of the examples I have seen work well enough using MERGE, UNION, or JOIN but I can't get them to work for this much larger dataset, which is why it has been giving me so much trouble. I am not very experienced with SQL so I would appreciate some additional padding to the explanation.
Where ABCD are columns and 1 is data: Here is the master table
a b c d
1 1 1 1
Here is the update table:
b c d e
1 _ 1 1
Only imagine that there are 100 columns and 100 rows to append to the 10,000 stored.
Desired:
a b c d e
1 1 1 1
_ 1 _ 1 1
Or even
a b c d
1 1 1 1
_ 1 _ 1
e:
This answer is exactly what I want, but it doesn't seem possible in TSQL
https://stackoverflow.com/a/52524364/11777090
do union all
select a,b,c,d,0 from table
union all
select 0,b,c,d,e from table

Concatenating codes to obtain sum

I've been for tha past 2 days trying to solve this problem but can't even seem to find the right terms to google it.
I have 3 tables.
This one, with client codes that changed:
ActualCode=111111111 PreviousCode=44444444
And these two tables with value 1 and value 2:
PreviousCode=11111111, Value1= 50,00, Value2= 0,00
ActualCode=44444444 , Value1= 0,00, Value2 = 50,00
I need to sum the values for each relation of Previous and Actual codes from the first table.
I.E.
For
ActualCode=11111111, PreviousCode=44444444
I need to be able to get:
Code=11111111 Value1=50,00 Value2=50,00
Looking forward for your answer :D
Thanks,
P
You can join the tables and sum the values:
select c.actualcode,
sum(ac.value1) + sum(pc.value1) as value1,
sum(ac.value2) + sum(pc.value2) as value2
from codes c
join actualcodes ac on c.actualcode = ac.actualcode
join previouscodes pc on c.previouscode = pc.previouscode
group by c.actualcode;
Rextester Demo
If you could have values in the main table that don't have corresponding rows in the values tables, then you should use outer joins instead.

Oracle query to link records from same table which maps to mapping table

Apologies for the horrible question title,not sure how to articulate it better.
So to start out.
**Table Dummy_Table**
id description filter_key
1 Test Record1 filterkey1
2 Test Record2 filterkey1
3 Test Record1 filterkey2
4 Test Record2 filterkey2
The records with filterkey1 map to a table like this
**Table Mapping_table**
Dummy_Table_id someother_key (one(Dummy_Table_id) to many(someother_key)
1 x
1 y
1 z
1 r
2 y
2 r
Now : In a query I map the id's to each other in the Dummy_Table using the description,so I end up with a resultset like this
id_for_filter_key1 id_for_filterkey2
1 3
2 4
Ok,thats all good and well,it's the next step I'm having a issue with.I need to add records to Table Mapping_table which should end up looking like this
**Table Mapping_table**
Dummy_Table_id someother_key
3 x
3 y
3 z
3 r
4 y
4 r
So in essence whatever the id is for filterKey1 I would like to apply it's someother_key to the id's with filterkey2 (filterKey1 and filterkey2 relate to each other with their descriptions)
Now I don't know if I'm over complicating this.I'll tell you what my problem is.
I have records in the database with filterkey1 which map to the mapping table.Afterwords I added the records with filterkey2.These rows are duplicates just with another filter key.Now I need to apply the same mappings to the records with filterkey2
Changing the table structure is not a option atm.I need to give the DBA a insert query to achieve this.
Many thanks in advance.
This query gives missing values:
SELECT d.id_for_filterkey2, m.someother_key
FROM Mapping_table m
JOIN Dummy_Table d ON m.Dummy_Table_id = d.id_for_filter_key1
Demo: http://sqlfiddle.com/#!4/61ddfe/2
When we have missing values, then we can merge them into Mapping_table:
MERGE INTO Mapping_table m
USING( copy-the-above-query-and-paste-it-here) x
ON (x.id_for_filterkey2 = m.Dummy_Table_id)
WHEN NOT MATCHED THEN
INSERT( Dummy_Table_id, someother_key )
VALUES( x.id_for_filterkey2, x.someother_key );
Demo: http://sqlfiddle.com/#!4/d74304/3

Finding contiguous regions in a sorted MS Access query

I am a long time fan of Stack Overflow but I've come across a problem that I haven't found addressed yet and need some expert help.
I have a query that is sorted chronologically with a date-time compound key (unique, never deleted) and several pieces of data. What I want to know is if there is a way to find the start (or end) of a region where a value changes? I.E.
DateTime someVal1 someVal2 someVal3 target
1 3 4 A
1 2 4 A
1 3 4 A
1 2 4 B
1 2 5 B
1 2 5 A
and my query returns rows 1, 4 and 6. It finds the change in col 5 from A to B and then from B back to A? I have tried the find duplicates method and using min and max in the totals property however it gives me the first and last overall instead of the local max and min? Any similar problems?
I didn't see any purpose for the someVal1, someVal2, and someVal3 fields, so I left them out. I used an autonumber as the primary key instead of your date/time field; but this approach should also work with your date/time primary key. This is the data in my version of your table.
pkey_field target
1 A
2 A
3 A
4 B
5 B
6 A
I used a correlated subquery to find the previous pkey_field value for each row.
SELECT
m.pkey_field,
m.target,
(SELECT Max(pkey_field)
FROM YourTable
WHERE pkey_field < m.pkey_field)
AS prev_pkey_field
FROM YourTable AS m;
Then put that in a subquery which I joined to another copy of the base table.
SELECT
sub.pkey_field,
sub.target,
sub.prev_pkey_field,
prev.target AS prev_target
FROM
(SELECT
m.pkey_field,
m.target,
(SELECT Max(pkey_field)
FROM YourTable
WHERE pkey_field < m.pkey_field)
AS prev_pkey_field
FROM YourTable AS m) AS sub
LEFT JOIN YourTable AS prev
ON sub.prev_pkey_field = prev.pkey_field
WHERE
sub.prev_pkey_field Is Null
OR prev.target <> sub.target;
This is the output from that final query.
pkey_field target prev_pkey_field prev_target
1 A
4 B 3 A
6 A 5 B
Here is a first attempt,
SELECT t1.Row, t1.target
FROM t1 WHERE (((t1.target)<>NZ((SELECT TOP 1 t2.target FROM t1 AS t2 WHERE t2.DateTimeId<t1.DateTimeId ORDER BY t2.DateTimeId DESC),"X")));