Sql server join 3 tables and get the latest from 3rd table - sql-server-2008

Hi all I am having 3 tables as follows
Technology_table
Technology_ID Technology_Name
10 Asp.Net
20 C#
Question_table
QUESTION_ID Technology_ID QUESTION_DESCRIPTION
1 10 First ques in Asp.net
2 20 First ques in C#
Reply_table
QUESTION_ID Technology_ID Reply_Date Reply_Message
1 10 2016-01-23 I am first to post
1 10 2016-01-24 I am second to post
I have written the following query but not getting the result as expected
select
FI.QUESTION_ID,FI.QUESTION_TITLE,FI.USER_NAME,FI.DATE_POSTED,
FI.[DATE_REPLIED],FI.RepliedName,FI.VIEW_COUNT,FI.REPLY_COUNT,
FI.REPLY_MESSAGE,TT.TECHNOLOGY_ID,TT.TECHNOLOGY_NAME
from FORUM_TECHNOLOGY TT,
( select distinct
TQ.TECHNOLOGY_ID,TQ.QUESTION_ID,TQ.QUESTION_TITLE,TQ.USER_NAME,
TQ.DATE_POSTED,
TR.[DATE_REPLIED],
TR.USER_NAME as RepliedName,
TQ.VIEW_COUNT,TQ.REPLY_COUNT,TR.REPLY_MESSAGE
from FORUM_QUESTIONS TQ
LEFT OUTER JOIN FORUM_REPLIES TR
ON TR.TECHNOLOGY_ID=TQ.TECHNOLOGY_ID
and TR.QUESTION_ID = TQ.QUESTION_ID
and TR.[DATE_REPLIED] in (
select MAX(TR.[DATE_REPLIED])
from FORUM_REPLIES TR
group by TR.QUESTION_ID
)
) FI
where FI.TECHNOLOGY_ID =TT.TECHNOLOGY_ID
and TT.TECHNOLOGY_ID = #TechID
I also tried in this way
select t1.QUESTION_ID,oa.USER_NAME,oa.REPLY_MESSAGE
from FORUM_QUESTIONS t1
cross apply(select top 1 * from FORUM_REPLIES
where QUESTION_ID = t1.QUESTION_ID
order by DATE_REPLIED desc)oa
join FORUM_TECHNOLOGY t2 on oa.TECHNOLOGY_ID = t2.TECHNOLOGY_ID
AND oa.QUESTION_ID = t1.QUESTION_ID
I would like to display only one instead of duplicates
Can some one help me

This assumes that your DATE_REPLIED has a valid time component and isn't just omitted or defaulted to midnight.
SELECT FQ.QUESTION_ID
, FQ.QUESTION_TITLE
, FQ.USER_NAME
, FQ.DATE_POSTED
, FR.DATE_REPLIED
, FR.RepliedName
, FQ.VIEW_COUNT
, FI.REPLY_COUNT
, FR.REPLY_MESSAGE
, TT.TECHNOLOGY_ID
, TT.TECHNOLOGY_NAME
FROM FORUM_TECHNOLOGY AS TT
INNER JOIN FORUM_QUESTION AS FQ
ON FQ.TECHNOLOGY_ID = TT.TECHNOLOGY_ID
LEFT OUTER JOIN (
SELECT QUESTION_ID
, COUNT(*) AS REPLY_COUNT
, MAX(DATE_REPLIED) AS DATE_REPLIED
FROM FORUM_REPLIES
GROUP BY QUESTION_ID
) AS FI
ON FI.QUESTION_ID = FQ.QUESTION_ID
INNER JOIN FORUM_REPLIES AS FR
ON FR.QUESTION_ID = FI.QUESTION_ID
AND FR.DATE_REPLIED = FI.DATE_REPLIED

Related

selection of data from multiple table date by date

I have 3 different table named job_party, job_party_details and job_party_delv. In which job_party is the main table and others are detailed tables. I am trying to gather data date by date from all these tables. I wrote the following query and getting perfect data but the problem is data of job_party_details comes first and job_party_delv comes latter. I want all data at once as per the date.
SELECT job_party.on_date
, SUM(job_party_details.qty) as detail_qty
, NULL as delv
FROM job_party_details d
JOIN job_party p
on d.jp_id = p.id
where p.party_id = 9
and d.i_id = 1
GROUP
BY p.on_date
UNION
SELECT p.on_date
, NULL as detail_qty
, SUM(d.d_qty) as delv
FROM job_party_delv d
JOIN job_party p
on d.jp_id = p.id
where p.party_id = 9
and d.i_id = 1
GROUP
BY p.on_date
Replace NULL with 0 then make the query as a sub-query and perform another SUM on the outer query GROUP BY on_date like this:
SELECT on_date,SUM(detail_qty) as detail_qty, SUM(delv) as delv
FROM
(SELECT job_party.on_date
, SUM(job_party_details.qty) as detail_qty
, 0 as delv
FROM job_party_details d
JOIN job_party p
on d.jp_id = p.id
where p.party_id = 9
and d.i_id = 1
GROUP
BY p.on_date
UNION
SELECT p.on_date
, 0 as detail_qty
, SUM(d.d_qty) as delv
FROM job_party_delv d
JOIN job_party p
on d.jp_id = p.id
where p.party_id = 9
and d.i_id = 1
GROUP
BY p.on_date) A GROUP BY on_date;

SQL select and compare

I am trying to retrieve everything from client and bond table where the client.id is not equal to bond.client and bond client.bond is not equal to bond.id. My query did not work and returns the whole list instead. How can i solve this problem? My query wants to output 4 , 5 from client table and 5, 5 from bond table as the result
Client table
Id Bond
1 2
2 3
4 5
Bond table
Id Client
2 1
3 2
5 5
.
SELECT * FROM `client_table`
INNER JOIN `bond_table`
where client_table.id != bond_table.client and client_table.bond != bond_table.id
Please try this:
SELECT c.ClientID, c.BondID from client_table c
left join bond_table b
on c.clientID = b.clientID
where b.clientID is null
UNION
SELECT b.ClientID, b.BondID from bond_table b
left join client_table c
on c.clientID = b.clientID
where c.clientID is null
could be using not in clause
SELECT * FROM `client_table`
INNER JOIN `bond_table` on client_table.id
not in ( select bond_table.client from bond)
AND client_table.bond not in ( select bond_table.id from bond)
but based on the resukt you show in the comment you should use OR (and not AND)
SELECT * FROM `client_table`
INNER JOIN `bond_table` on client_table.id
not in ( select bond_table.client from bond)
OR client_table.bond not in ( select bond_table.id from bond)

How group values in Mysql query?

I have query:
SELECT p.`obj_id` ,
p.`alt_name` ,
o.`name`,
p.`id`,
oc.`text_val`,
oc.`float_val`
FROM `cms3_hierarchy` p
LEFT JOIN `cms3_objects` o
ON p.`obj_id` = o.`id`
LEFT JOIN `cms3_object_content` oc
ON p.`obj_id` = oc.`obj_id`
WHERE (oc.`field_id` = 221 OR oc.`field_id` = 248 )
AND (p.`rel`=903687) LIMIT 0,50
But answer like this:
obj_id name id 221 248
1 first 2 null
1 first null 3
Well, i have one obj_id with different values.
But for me this is look like this:
obj_id name id 221 248
1 first 2 3
How to do this?
Conditions on the right table of a LEFT JOIN should be specified only inside the ON clause, when they are in the WHERE clause, the join automatically turns into an INNER JOIN because of NULL comparison.
Also, use IN() to compare the same column to multiple values instead of OR . I also used MAX() to group the rows into one row, so :
SELECT p.obj_id , p.alt_name , o.name,p.id,
MAX(CASE WHEN oc.field_id = 221 THEN oc.text_val END) as col_221,
MAX(CASE WHEN oc.field_id = 1123 THEN oc.text_val END) as col_1123,
MAX(oc.float_val)
FROM cms3_hierarchy p
LEFT JOIN cms3_objects o
ON p.obj_id = o.id
LEFT JOIN cms3_object_content oc
ON p.obj_id = oc.obj_id and oc.field_id in(221,248,1123)
WHERE p.rel=903687
LIMIT 0,50
GROUP BY p.obj_id , p.alt_name , o.name,p.id

MySQL >, <, and missing by group

I have two tables in MySQL that I'm comparing with the following attributes:
tbl_fac : facility_id, chemical_id, criteria
10 , 25 , 50
10 , 26 , 60
10 , 27 , 60
11 , 25 , 30
11 , 27 , 31
etc...
tbl_samp: sample_id, chemical_id, result
5 , 25 , 51
5 , 26 , 61
6 , 25 , 51
6 , 26 , 61
6 , 27 , 500
etc....
These tables are joined by chemical_id (many-to-many---- ugh), and there are several thousand facility_id's, and several hundred chemical_id's for each facility_id. There are also several thousand sample_id's, each with several hundred chemical_id's for each sample_id. All-in-all, there are around 500,000 records in tbl_fac, and 1,000,000+ records in tbl_samp.
I'm trying to extract three groups of sample_id's from this dataset:
Group 1: any sample_id where tbl_samp.result > tbl_fac.criteria (i.e., result exceeds criteria)
Group 2: any sample_id where tbl_samp.result < tbl_fac.criteria, AND all tbl_fac.chemical_id's are present for that sample_id (i.e., result is less than criteria, and everything is there)
Group 3: any sample_id where tbl_samp.result < tbl_fac.criteria, BUT one or more tbl_fac.chemical_id's are missing in the sample_id (i.e., result is less than criteria, but something is missing)
Here's the Question: How do I get all three Groups efficiently in one query?
I've tried:
select *
from tbl_fac
left join tbl_samp
on tbl_fac.chemical_id = tbl_samp.chemical_id
But this only yields values that are missing for the entire dataset (not the individual samples). I have a hackish query working that uses a third table to join tbl_fac and tbl_samp, but it is so ugly I'm actually embarrassed to post it....
As always, many thanks in advance for your thoughts on this one!
Cheers,
Josh
EDIT: Ideally, I would like the sample_id and Group returned -- with just one Group per sample ID (my knowledge of the data indicates that they will always fall into one of the three categories above).
This answer makes the assumption that there is a unique constraint on facility_id and chemical_id in tbl_fac and a unique constraint on sample_id and chemical_id in tbl_samp. What I did was build up the query one step at a time. Whether this is efficient remains to be seen.
Group 1: any sample_id where tbl_samp.result > tbl_fac.criteria (i.e., result exceeds criteria)
SELECT tbl_samp.sample_id,
'ResultsGreaterThanCriteria' AS samplegroup
FROM tbl_fac
INNER JOIN tbl_samp
ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE tbl_samp.result > tbl_fac.criteria
GROUP BY tbl_samp.sample_id
Group 2: any sample_id where tbl_samp.result < tbl_fac.criteria, AND all tbl_fac.chemical_id's are present for that sample_id (i.e., result is less than criteria, and everything is there)
SELECT tbl_samp.sample_id,
'ResultLessThanCriteriaAndAllChems' AS samplegroup
FROM tbl_fac
INNER JOIN tbl_samp
ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE tbl_samp.result < tbl_fac.criteria
AND NOT EXISTS (SELECT *
FROM tbl_fac tf
LEFT JOIN tbl_samp ts
ON tf.chemical_id = ts.chemical_id
WHERE ts.chemical_id IS NULL
AND tbl_samp.sample_id = ts.sample_id)
GROUP BY tbl_samp.sample_id
Group 3: any sample_id where tbl_samp.result < tbl_fac.criteria, BUT one or more tbl_fac.chemical_id's are missing in the sample_id (i.e., result is less than criteria, but something is missing)
SELECT tbl_samp.sample_id,
'ResultsLessThanCriteriaWithMissingChems' AS samplegroup
FROM tbl_fac
INNER JOIN tbl_samp
ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE tbl_samp.result < tbl_fac.criteria
AND EXISTS (SELECT *
FROM tbl_fac tf
LEFT JOIN tbl_samp ts
ON tf.chemical_id = ts.chemical_id
WHERE ts.chemical_id IS NULL
AND tbl_samp.sample_id = ts.sample_id)
GROUP BY tbl_samp.sample_id
And finally, you union all three queries together and get:
SELECT tbl_samp.sample_id,
'ResultsGreaterThanCriteria' AS samplegroup
FROM tbl_fac
INNER JOIN tbl_samp
ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE tbl_samp.result > tbl_fac.criteria
GROUP BY tbl_samp.sample_id
UNION ALL
SELECT tbl_samp.sample_id,
'ResultLessThanCriteriaAndAllChems' AS samplegroup
FROM tbl_fac
INNER JOIN tbl_samp
ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE tbl_samp.result < tbl_fac.criteria
AND NOT EXISTS (SELECT *
FROM tbl_fac tf
LEFT JOIN tbl_samp ts
ON tf.chemical_id = ts.chemical_id
WHERE ts.chemical_id IS NULL
AND tbl_samp.sample_id = ts.sample_id)
GROUP BY tbl_samp.sample_id
UNION ALL
SELECT tbl_samp.sample_id,
'ResultsLessThanCriteriaWithMissingChems' AS samplegroup
FROM tbl_fac
INNER JOIN tbl_samp
ON tbl_fac.chemical_id = tbl_samp.chemical_id
WHERE tbl_samp.result < tbl_fac.criteria
AND EXISTS (SELECT *
FROM tbl_fac tf
LEFT JOIN tbl_samp ts
ON tf.chemical_id = ts.chemical_id
WHERE ts.chemical_id IS NULL
AND tbl_samp.sample_id = ts.sample_id)
GROUP BY tbl_samp.sample_id
SELECT
sample_id,
IF(result = criteria, -1, /* unspecified behavior */
IF(result > criteria, 1,
IF(nb_chemicals = total_nb_chemicals, 2, 3))) AS grp
FROM (
SELECT s.result, s.sample_id, f.criteria, f.chemical_id,
COUNT(DISTINCT f.chemical_id) AS nb_chemicals
FROM tbl_fac f JOIN tbl_samp s
ON f.chemical_id = s.chemical_id
GROUP BY s.sample_id
) t
CROSS JOIN (
SELECT COUNT(DISTINCT chemical_id) AS total_nb_chemicals
FROM tbl_fac
) u
New solution:
SELECT
s.sample_id,
IF(s.result = f.criteria, -1, /* unspecified behavior */
IF(s.result > f.criteria, 1,
IF(sample_nb_chemicals = total_nb_chemicals, 2, 3))) AS grp
FROM
tbl_fac f JOIN tbl_samp s
ON f.chemical_id = s.chemical_id
JOIN (
SELECT s.sample_id,
COUNT(DISTINCT f.chemical_id) AS sample_nb_chemicals
FROM tbl_fac f JOIN tbl_samp s
ON f.chemical_id = s.chemical_id
GROUP BY s.sample_id
) u
ON s.sample_id = u.sample_id
CROSS JOIN (
SELECT COUNT(DISTINCT chemical_id) AS total_nb_chemicals
FROM tbl_fac
) v
GROUP BY sample_id, grp

MySQL JOIN WHERE forgein Key = id1 AND forgein Key = id2

I am having a bit of a brain block with this problem and I am finding it hard to search for a solution because I cant phrase the question correctly to bring up the relevant information.
I am trying to get back "fProduct" record from the table below where it has a "fAttribute"
of 2 and 20.
id fAttribute fProduct
19 2 2967
48 2 2923
50 2 3008
51 20 3008
52 2 2295
53 20 2295
My statment below produces 0 results when I would expect to return fProduct's 2295 and 3008.
SELECT fProduct
FROM tableName
WHERE fAttribute = 2 AND fAttribute = 20
GROUP BY fProduct
Can anyone help please?
You can either use INNER JOINS or use EXISTS conditions:
INNER JOIN:
SELECT DISTINCT a.fProduct
FROM MyTable a
INNER JOIN MyTable b ON a.fProduct = b.fProduct AND b.fAttribute = 2
INNER JOIN MyTable c ON a.fProduct = c.fProduct AND c.fAttribute = 20
EXISTS:
SELECT afproduct
FROM MyTable a
WHERE EXISTS (SELECT b.id FROM MyTable b WHERE a.fProduct = b.fProduct AND b.fAttribute = 2)
AND EXISTS (SELECT c.id FROM MyTable c WHERE a.fProduct = c.fProduct AND c.fAttribute = 20)
A join should help:
SELECT distinct a.fProduct
FROM tableName as a
join tableName as b on b.product = a.product
WHERE a.fAttribute = 2 and b.fAttribute = 20
Since your are already doing a GROUP BY just change your WHERE clause to an OR or an IN and add the HAVING COUNT(fattribute) = 2 which makes sure it has both.
SELECT fproduct
FROM tablename
WHERE fattribute IN (2 , 20)
GROUP BY fproduct
HAVING COUNT(fattribute) = 2