I have three tables, the first one is called "File" :
JobId FilenameId FileId
5 2 1
7 3 2
And the second one is called "Filename"
Filename FilenameId
File1 2
File2 3
And the third one is called "Client" :
ClientId JobId
1 5
2 7
Now I want to get the ClientId of File1, how can I do it? I'm new to SQL.
Thanks.
Edit : this is what I tried but it's not working
Select c.ClientId
From `File` f, Filename fn, Client c
Where f.FilenameId = fn.FilenameId and f.JobId = c.JobId and fn.Filename = "File1";
First, I hate the negative banter that sometimes goes on, but yes, you need to get yourself more educated in SQL during your learning. Look here at real-life scenarios and how people offer different solutions to the same.
Now to YOUR question. First, get rid of old style sql where you put all the join criteria in your where clause. Get started knowing the proper relationships between the tables. Second, your WHERE clause should be the basis of your specific criteria -- such as you want File 1. From that, get to the other tables. My personal standard of SQL coding shows first the what criteria do I want and from what table. Ensure indexes are available for optimizing the query. THEN join to the other tables to get the other elements needed to complete the row of data. (Good use of table "aliases", and keep with it).
First, your main criteria. Simple enough.
select
fn.FileNameID,
fn.FileName
from
FileName fn
where
fn.FileName = 'File1'
From there, do your joins to get the next pieces of information from file to client relationships
select
fn.FileNameID,
fn.FileName,
c.clientID
from
FileName fn
JOIN File f
on fn.FileNameID = f.FileNameID
JOIN Client c
on f.JobID = c.JobID
where
fn.FileName = 'File1'
Notice the hierarchical indentation from file name to the file, then from file to the client... you can visually see how the tables are related. Then, just grab your other columns as you need and add to your field list with proper aliases.
Try this:
select ClientId from Client where JobId in (select JobId from File where FilenameId in (select FilenameId from Filename where Filename="File1"));
Related
so I have a possibly silly question, but I'm looking for a basic approach or strategy for the following problem.
I have 1 master file and 3 source files, lets call them master, src1, src2, and src3. The master file is SUPPOSED to have the same records as the 3 source files combined, however, the master file has more records than the sum of all 3 sources. My goal is to validate that all records in said src1-3 are inside the master file AND also extract the records from the master that aren't in any 1 of the 3 sources. Additionally, each of the 4 files have different (but similar) headers
I have been able to find the distinct records from src1 (and subsequent sources) and mapped it to the matching records in the master file by using the following :
WITH tmp1 AS (
SELECT src1.*
FROM src1 as s1
LEFT JOIN master as mstr
ON (
s1.name = mstr.fname
s1.quant = mstr.qty
s1.item = mstr.obj
s1.price = mstr.prc
s1.age = mstr.time_since_dob
)
) SELECT DISTINCT primaryKey from tmp1;
Using this, I can get a count of distinct matches between the two files that are present in src1 and if that matches the count from select distinct PK from src1 then I'm in decent shape. Albeit, I know that using the criteria above I could easily get many collision since several records could have the same name, quantity, item, price, etc... But suffice it to say, using the above criteria I can get unique matches since there are no matching ID's between the two tables or anything like that. Additionally, the join criteria for each source is slightly different so I had to do the above 3 separate times and validate each source independently.
Having done the above along with some other analysis, I have been able to validate that each distinct record from src1-3 has at least 1 distinct match in the master file. I'm having issue, however, with the second half of this challenge where I have to select the records from the master file that did NOT have a corresponding match.
How can I select those records from the master file that were not matched? Can I do a simple
select * from master not in newView1 where newView1 is the combination of the 3 selects for the 3 sources? Again, I'm using different columns for each join condition so putting 3 sources under the same header might be difficult (but worth pursuing?). Another thing worth mentioning is that each file is ~1gb and the master file is ~3gb so time complexity is worth considering.
Thanks for all and any help.
First, using UNION ALL to get all matching rows and rows contained only in src1-3 tables.
Next, getting also rows of the master table that is contained only in the master table by joining with the tmp1 table.
Refer to the following query:
with tmp1(tbl,name,quant,item,price,age,fname,qty,obj,prc,time_since_dob) as (
select 'src1',s1.*,m.* from src1 s1 left join master1 m on
s1.name=m.fname and
s1.quant=m.qty and
s1.item=m.obj and
s1.price=m.prc and
s1.age=m.time_since_dob
union all
select 'src2',s2.*,m.* from src2 s2 left join master1 m on
s2.name=m.fname and
s2.quant=m.qty and
s2.item=m.obj and
s2.price=m.prc and
s2.age=m.time_since_dob
union all
select 'src3',s3.*,m.* from src3 s3 left join master1 m on
s3.name=m.fname and
s3.quant=m.qty and
s3.item=m.obj and
s3.price=m.prc and
s3.age=m.time_since_dob
)
select 'master',m.fname,m.qty,m.obj,m.prc,m.time_since_dob from master1 m left join tmp1 t on
m.fname=t.name and
m.qty=t.quant and
m.obj=t.item and
m.prc=t.price and
m.time_since_dob=t.age
where t.name is null
union all
select t.tbl,t.name,t.quant,t.item,t.price,t.age from tmp1 t
where t.fname is null
db fiddle
I'm trying to get the content of 3 different tables.
table A = Is containing our users list, table B = Is returning contracts related to users,table C = Is returning formula details related to the contracts.
In order to make it the right way, I'm using the following multi table request:
SELECT * FROM rscm_students A, rscm_files B, rscm_formulas C
WHERE B.dossier_status = 0
AND A.student_agency = :agency
AND B.file_student_id = A.id
AND B.file_formula_id = C.id
AND C.formula_place = 0
GROUP BY A.student_uniqid
ORDER BY B.file_date_create";
This is where the whole damn thing become a little complicated. It is returning the correct datas, but as the primary key of every table here is called "id". I can't do some foreach in php. If I got 3 contracts on 1 user, it impossible for me to regroup every contract in the same user array.
I'm still not an expert in SQL, that's why I'm using Phinx to control my database. This is also why my primary keys are named "id".
If you have a good idea, please let me know!
Alright, I will make an answer out of it.
First off, don't use
select *
The above select is fine for quick and dirty development prior to production. But it makes a mess out of things such as your joins with common column names coming out of multiple tables (like id and others).
Use modern explicit join syntax. Don't use the older join style. So use join and on.
Lastly with table aliases, create unique output column names for the id columns or other clashes such as
A.id as aid, B.id as bid
I have 5 different tables T_DONOR, T_RECIPIENT_1, T_RECIPIENT_2, T_RECIPIENT_3, and T_RECIPIENT_4. All 5 tables have the same CONTACT_ID.
This is the T_DONOR table:
T_RECIPIENT_1:
T_RECIPIENT_2:
This is what I want the final table to look like with more recipients and their information to the right.
T_RECIPIENT_3 and T_RECIPIENT_4 are the same as T_RECIPIENT_1 and T_RECIPIENT_2 except that they have different RECIPIENT ID and different names. I want to combine all 5 of these tables so on one line I can have the DONOR_CONTACT_ID which his information, and then all of the Recipient's information.
The problem is that when I try to run a query, it does not work because not all of the Donors have all of the recipient fields filled, so the query will run and give a blank table. Some instances I have a Donor with 4 Recipients and other times I have a Donor with only 1 Recipient so this causes a problem. I've tried running queries where I connect them with the DONOR_CONTACT_ID but this will only work if all of the RECIPIENT fields are filled. Any suggestions on what to do? Is there a way I could manipulate this in VBA? I only know some VBA, I'm not an expert.
First I think you want all rows from T_DONOR. And then you want to pull in information from the recipient tables when they include DONOR_CONTACT_ID matches. If that is correct, LEFT JOIN T_DONOR to the other tables.
Start with a simpler set of fields; you can add in the "name" fields after you get the joins set to correctly return the rest of the data you need.
SELECT
d.DONOR_CONTACT_ID,
r1.RECIPIENT_1,
r2.RECIPIENT_1
FROM
(T_DONOR AS d
LEFT JOIN T_RECIPIENT_1 AS r1
ON d.ORDER_NUMBER = r1.ORDER_NUMBER)
LEFT JOIN T_RECIPIENT_2 AS r2
ON d.ORDER_NUMBER = r2.ORDER_NUMBER;
Notice the parentheses in the FROM clause. The db engine requires them for any query which includes more than one join. If possible, set up your joins in Design View of the query designer. The query designer knows how to add parentheses to keep the db engine happy.
Here is a version without aliased table names in case it's easier to understand and set up in the query designer ...
SELECT
T_DONOR.DONOR_CONTACT_ID,
T_RECIPIENT_1.RECIPIENT_1,
T_RECIPIENT_2.RECIPIENT_1
FROM
(T_DONOR
LEFT JOIN T_RECIPIENT_1
ON T_DONOR.ORDER_NUMBER = T_RECIPIENT_1.ORDER_NUMBER)
LEFT JOIN T_RECIPIENT_2
ON T_DONOR.ORDER_NUMBER = T_RECIPIENT_2.ORDER_NUMBER;
SELECT T_DONOR.ORDER_NUMBER, T_DONOR.DONOR_CONTACT_ID, T_DONOR.FIRST_NAME, T_DONOR.LAST_NAME, T_RECIPIENT_1.RECIPIENT_1, T_RECIPIENT_1.FIRST_NAME, T_RECIPIENT_1.LASTNAME
FROM T_DONOR
JOIN T_RECIPIENT_1
ON T_DONOR.DONOR_CONTACT_ID = T_RECIPIENT_1.DONOR_CONTACT_ID
This shows you how to JOIN the first recipient table, you should be able to follow the same structure for the other three...
I wonder if any can help me understand something I'm trying to solve.
I'm working on a wordpress site but this is more a sql question as I'm just querying to get some results within a template file.
I have a gallery of pictures which are advert boxes, and I need to pull these in relation to a supplied movie name, to do this Im using some custom fields on the ad pic called 'adlink' (link off ad) and ad
I'm using the nextgen gallery plugin and querying those tables, and I have three tables in total that contain the data I need to query.
ngg_pictures, nggcf_field_values & nggcf_fields.
the nggcf tables are custom fields tables,
I have got so far I can get what I need in two seperate queries, but I can't combine these into one query as it means querying the nggcf_field_values table twice, which I can't seem to sort.
I have hardcoded the search criteria in for the mo, but the 'close-encounters' bit would be a passed var, and the '156' would be the pid from the first query.
SELECT `eg_ngg_pictures`.`filename`, `eg_nggcf_field_values`.`fid`, `eg_nggcf_field_values`.`pid`
FROM eg_ngg_pictures, eg_nggcf_field_values
WHERE ((`eg_nggcf_field_values`.`field_value` LIKE 'close-encounters') AND (`eg_nggcf_field_values`.`pid` = eg_ngg_pictures.pid))
SELECT `eg_nggcf_field_values`.`field_value`
FROM eg_nggcf_field_values, eg_nggcf_fields
WHERE ((`eg_nggcf_fields`.`field_name` = 'adlink') AND (`eg_nggcf_fields`.`id` = eg_nggcf_field_values.fid) AND (`eg_nggcf_field_values`.`pid` = '156'))
any help would be greatly appreciated, I can get the results with what I have, but I like to understand how to combine these two and write better SQl. Thanks MRO
After looking at the Wordpress extension, I think the eg_nggcf_fields is the table that contains the name for a custom field. The eg_nggcf_field_values table contains the values of that custom field per picture.
So if you're looking for two fields called moviename and adlink, you have to look up two rows in the field_values table. You can join a table twice if you give it a different alias:
select pic.filename
, pic.pid
, fv1.field_value as MovieName
, fv2.field_value as Adlink
from eg_ngg_pictures pic
inner join -- Find ID for the field called 'moviename'
eg_nggcf_fields f1
on f1.field_name = 'moviename'
inner join -- Find value for field moviename for this picture
eg_nggcf_field_values as fv1
on fv1.pid = pic.pid
and fv1.fid = f1.fid
inner join -- Find ID for the field called 'adlink'
eg_nggcf_fields f2
on f2.field_name = 'adlink'
inner join -- Find value for field adlink for this picture
eg_nggcf_field_values as fv2
on fv2.pid = pic.pid
and fv2.fid = f2.fid
where fv1.field_value like 'close-encounters'
First of all, I'd recommend sticking to modern ANSI syntax for JOINing tables, which means using the JOIN clause.
Instead of using:
FROM table1, table2 WHERE table1.id = table2.pid
use:
FROM Table 1 JOIN table2 ON table1.id = table2.id
For simplicity's sake, I'd also recommend you to alias tables, as that tends to make the code more readable. Instead of having to write out egg_ngg_pictures every time, you can simply refer to the alias you assign it instead.
Lastly, when you use a LIKE operator, you usually add a wild-card character (typically %. I.e. LIKE '%123' or LIKE '123%'). You seem to look only for complete matches, which means you can just stick to using =, as that should give you slightly better performance.
Now to rewrite your query, I'd use something like the following:
SELECT
pic.filename
, fieldval.fid
, fieldval.pid
, fieldval.field_value
FROM
eg_ngg_pictures pic
JOIN eg_nggcf_field_values fieldval ON fieldval.pid = pic.pid
JOIN eg_nggcf_fields fields ON fields.id = fieldval.fid
WHERE
((fieldval.field_value = 'close-encounters')
AND fields.field_name = 'ad_link'
Note that I am not able to test the query, as I do not have your schema. But by incorporating the two queries into a single query, the join on the field_Values.PID retreieved with the 'close_encounters' value should already exist.
If the query does not work, feel free to create a SQL fiddle with the relevant tables and some data, and I'll try and get it to work with that.
I have two columns, source and destination in table Hyperlink, to store the source and destination of hyperlinks.
source | destination
--------------------
a | b
b | c
c | d
c | b
There are two hyperlinks involving both b and c. The difference between the two hyperlinks is the direction of the hyperlink. However, my objective is to retrieve unique hyperlinks, no matter which direction. So for hyperlinks such as from b to c and from c to b, I just want to select one of them. Any one would do.
So my results should look like this:
source | destination
--------------------
a | b
b | c
c | d
So far I am able to implement this in Java, with some processing before I execute SQL statements using JDBC. However, this is going to be very tedious when the table becomes very large.
I wonder if there is anyway I can do this in SQL instead.
I tried SELECT DISTINCT source,destination FROM Hyperlink but it returns me the unique permutations. I need the unique combinations.
Thanks!
This is easily achievable with the least() and greatest() operator, but as MySQL doesn't support them you need to use a CASE construct to get the smaller/greater one. With two columns this is ok, but this solution gets pretty messy once more columns are involved
select distinct
case
when source < destination then source
else destination
end as source,
case
when source > destination then source
else destination
end as destination
from hyperlinks
Try the following query:
SELECT DISTINCT source, destination FROM hyperlink
MINUS
SELECT destination, source FROM hyperlinks WHERE source < destination;
This works for Oracle . If you're using PostgreSQL, DB2 or TSQL, use the EXCEPT keyword instead of MINUS.
EDIT:
There's no equivalent of these keywords in MySQL. You'll have to work around it by selecting the values as suggested by Jim Riordan. I'm not going to delete my answer in case if anyone needs to do it in any of the other four major DBMS.
You can use the union of two separate join queries like so:
SELECT
lhs.source, lhs.destination
FROM Hyperlink lhs
LEFT OUTER JOIN Hyperlink rhs
ON rhs.source = lhs.destination
WHERE rhs.source IS NULL
UNION
SELECT
lhs.source, lhs.destination
FROM Hyperlink lhs
JOIN Hyperlink rhs
ON rhs.source = lhs.destination
WHERE rhs.destination <> lhs.source
ORDER BY source;
The first query gets the links that don't have the source as the destination, the second gets the matches that have source as the destination, but different opposites. It's probably not the fastest implementation but ensuring you have indexes on the source and destination columns will help it along, whether it will be performant for you depends how big the Hyperlink table is or is likely to get.
I tried this query and it worked for me
SELECT table1.Source, table1.Destination FROM dbo.hyperlinks table1 WHERE NOT EXISTS
(SELECT * FROM hyperlinks table2 WHERE table1.Source = table2.Destination AND table2.Source = table1.Destination)
UNION
SELECT TOP 1 table1.Source, table1.Destination FROM hyperlinks table1 WHERE
(SELECT COUNT(*) FROM hyperlinks table2 WHERE table1.Source = table2.Destination AND table2.Source = table1.Destination) > 0