sql multiple self joins efficient - sql

I have a table that looks like the one below. I need to write a query to find all names that are present in all the sources. In the example below this is only "john" & "mark".
source name
a john
b john
c john
d john
a pat
b pat
a mark
b mark
c mark
d mark

Using the ALL statement, you can get the results you are expecting. Like this:
SELECT Name FROM dummy WHERE Source >= ALL (SELECT DISTINCT source FROM dummy);
See it in action: here

One method uses counting:
select name
from t
group by name
having count(distinct source) = (select count(distinct t2.source) from t t2);

Related

MS Access join on like returning null column

I have two tables in MS Access that have the same Name_ID column, the only problem is that they differ slightly. Name_ID in table 1 looks like this:
Name_ID
Newton, Kate Little
River, Jane Armen
Barker, Bob Jep
Jake, Lee
And in table 2 it looks like this:
Name_ID
NEWTON, KATE L MD
RIVER, JANE A DO MS
BARKER, BOB J. (MD)
JAKE, LEE I.
I'm struggling with how to join the tables. I tried doing a join using like, based on Access/SQL Server 2008 Join using Like not working, but it's not working:
Select table1.*, table2.col from table1
left join
table2
on table1.Name_ID like '*' & table2.Name_ID & '*';
I also tried:
Select table1.*, table2.col from table1
left join
table2
on instr(table1.Name_ID, table2.Name_ID) > 0;
Both queries execute, but return blank columns. Any idea why it's not working, or a better way?
Both queries are looking for a full name string within another full name string. How would you expect Newton, Kate Little to match to *NEWTON, KATE L MD*? And for the second query, NEWTON, KATE L MD is not within Newton, Kate Little.
Probably best can do is extract last name part and match on that. Assumes names are not repeated and not multiple people with same last name and always last name followed by a comma.
SELECT Table1.Name_ID, Table2.Name_ID
FROM Table1 LEFT JOIN Table2
ON Table1.Name_ID LIKE Left(Table2.Name_ID, InStr(Table2.Name_ID,",")) & "*";

Oracle SQL - How to dynamically replace values of select return?

I have the following view X
SELECT
ssn AS "Return1"
bla AS "Return2"
dla AS "Return3"
FROM v_stored_values
When using this view, I want to replace the number value of "svn" with a string value that can be found in the following view Y
SELECT
ssn AS "Return1"
string AS "Return2"
FROM v_ssn
So instead of
ssn | bla | dla
342 dff fdd
it should be
name | bla | dla
Thomas dff fdd
What would be the best way to combine those two views, who otherwise share no similarities, in a query?
You seem to be looking for a join. Assuming that v_ssn has columns ssn and name, that would look like:
select s.name return1, v.bla return2, v.dla return3
from v_stored_values v
inner join v_ssn s on s.ssn = v.ssn
If there is a possibility that some of ssns from v_stored_value are not available in v_ssn, you might want to use a left join instead, so the records are not eliminated from the resultset.

Select multiple results from sub query into single row (as array datatype)

I'm trying to solve a small problem with a SQL query in an oracle database. Let's assume I have these tables:
One table that holds information about cars:
tblCars
ID Model Color
--------------------
1 Volvo Red
2 BMW Blue
3 BMW Green
And another one containing information about drivers:
tblDrivers
ID fID_tblCars Name
---------------------------
1 1 George
2 1 Mike
3 2 Jason
4 2 Paul
5 2 William
6 3 Steve
Now, let's pretend that to find out the popularity of the cars, I want to create reports that contain the data about the cars and the people that are driving them (which seems a very reasonable thing one would accomplish with a database).
This "ReportObject" would have a string for the model, a string for the color and an array (or a list) of strings for the drivers.
Currently, I do this with two queries, in the first I select the cars
SELECT ID, Model, Color FROM tblCars
and create a report object for each result.
Then, I would take each result and get the drivers for each specific car
SELECT Name FROM tblDrivers WHERE fID_tblCars = ResultObject.ID
Basically, step one gives me a resulting data set that looks like this:
Result
------------------------------------------
ColumnID ColumnModel ColumnColor
Type Integer Type String Type String
and now, if I will have more cars in the future, I will have to make a lot of additional queries, one for each row in the resulting table.
When I try this:
SELECT Model, Color, (SELECT Name FROM tblDrivers WHERE tblDrivers.fID_tblCars = tblCars.ID) as Name FROM tblCars
I get some error message telling me that one result in the row contains multiple elements (which is what I want!).
I want the result to look like this:
Result
--------------------------------------------------------
ColumnID ColumnModel ColumnColor ColumnName
Type Integer Type String Type String Type Array
So when I build my report object, I could do something like this:
foreach (var Row in Results)
{
ReportObject.Model = Row.Model;
ReportObject.Color = Row.Color;
foreach (string Driver in Row.Name)
{
ReportObject.Drivers.Add(Driver);
}
}
Am I completely missing my basics here or do I have to split this up in multiple queries?
Thanks!
This works in Oracle. In the SQL Fiddle example I couldn't get the IDENTITY or the PRIMARY KEYS to work when creating the table (never used Oracle SQL before)
SELECT c.id,
c.model,
c.color,
LISTAGG(d.name, ',') WITHIN GROUP (ORDER BY d.name) AS "Drivers"
FROM tblCars c
JOIN tblDrivers d
ON c.id = d.fID_TblCars
GROUP BY c.id,
c.model,
c.color
ORDER BY c.Id
SQL Fiddle Example

MS Access: Selecting the first item according to a rank

Imagine I have a query called QueryA that returns stuff like this:
Employee Description Rank
John Happy 1
John Depressed 3
James Happy 1
James Confused 2
Mark Depressed 3
I am trying to make a query that grabs the Employee and the Description, but only one description -- the one with the best "rank." (the lower the rank the better). I sort QueryA by Employee then by Rank (descending).
So I'd want my new query QueryB to show that John as Happy, James as Happy, and Mark as Depressed.
However I try selecting Employee and then First of Description and it doesn't always work.
I'm not able to check this for Access, but it should work fine. Check my SQL Fiddle
select
r.employee, d.description
from
table1 as d
inner join (select min(rank) as rank, employee
from
table1
group by employee) r on d.rank = r.rank
and d.employee = r.employee

Find and group duplicates

Hopefully I'm able to explain what I'm trying to achieve, it's a bit complicated I think.
I have two tables like this:
ID | Names
--------------
A | Name1
B | Name2
C | Name3
ID | md5s
--------------
A | a
A | b
B | c
C | a
C | c
I'm trying to achieve this: In the end I want to have a list of all "Names" that have duplicate MD5 values and in which other "Names" these MD5 values were found.
So I want to get something like this:
Name1 has 5 duplicate entries in "md5s" with Name8, 4 with Name10 ...
I need a list for all "Names" like described above.
Hopefully that makes sense to someone. :)
I already tried it with this SQL statement:
SELECT names,COUNT(names) AS Num FROM tablename GROUP BY names HAVING(Num > 1);
But that gives me only the md5s that are duplicates. The relation to the rest is totally missing.
*edit:fixed typo
I feel like there must be a better solution than this, but here's what I've thrown together for you:
SELECT a.names NAME,
b.names DUPE_NAME,
COUNT(*) NUM_DUPES
FROM names_tbl a, names_tbl b, md5_tbl md5a, md5_tbl md5b
WHERE a.id < b.id
AND a.id = md5a.id
AND b.id = md5b.id
AND md5a.md5 = md5b.md5
GROUP BY a.names, b.names
ORDER BY a.names
The rule of thumb with finding duplicates is that you probably need to do a self join. This would be simpler if the names and their associated md5's were in the same record, but because they're in separate tables I think you need two versions of each table.