mysql - possible to join on more than one field? - sql

I'm trying to write a join statement, but am finding that the query I'm running outputs the same information for each title found. It seems like I need to join tables on multiple fields, and I'm not sure that's possible? It's a little hard to explain, but the code below shows what I'm trying to accomplish and what's actually happening... Hopefully, someone will be able to point me in the right direction?
+----------------------------------------------------+
TABLE: NODE N
+----------------------------------------------------+
nid | vid | type | language | title | uid
22196 | 22196 | einfo | en | Contact 15 | 15
22040 | 22040 | fmp | en | John Doe | 15
22043 | 22043 | fmp | en | Jane Doe | 15
+----------------------------------------------------+
TABLE: CONTENT_FIELD_PN P
+----------------------------------------------------+
vid | nid | delta | field_name_nid
22196 | 22196 | 0 | 22040
22196 | 22196 | 1 | 22043
+----------------------------------------------------+
TABLE: CONTENT_FIELD_PP PP
+----------------------------------------------------+
vid | nid | delta | field_homephone_value
22196 | 22196 | 0 | 6505551212
22196 | 22196 | 1 | 6505551444
I'm trying to write a join statement that will produce:
+----------------------------------------------------+
TRYING TO OUTPUT
+----------------------------------------------------+
title | field_homephone_value | delta
John Doe | 6505551212 | 0
Jane Doe | 6505551444 | 1
+----------------------------------------------------+
WHAT IS CURRENTLY BEING OUTPUT
+----------------------------------------------------+
title | field_homephone_value | delta
John Doe | 6505551212 | 0
Jane Doe | 6505551212 | 1
+----------------------------------------------------+
THE QUERY AS IT'S CURRENTLY WRITTEN
+----------------------------------------------------+
SELECT p.field_name_nid, n2.title, p.delta, pp.field_homephone_value
FROM node n
LEFT JOIN content_field_pn p ON n.nid = p.nid
LEFT JOIN node n2 ON p.field_name_nid = n2.nid
LEFT JOIN content_field_pp pp ON p.nid = pp.nid
WHERE n.nid = 22196
GROUP BY p.delta

You could use and in the on clause:
LEFT JOIN content_field_pp pp ON p.nid = pp.nid AND p.vid = pp.vid
^^^^^^^^^^^^^^^^^^

You may join on multiple fields...
SELECT `blah` FROM `a` LEFT JOIN `b` ON `b`.`id` = `a`.`id` AND `b`.`field2` = `a`.`field2`

Related

SQL - joining 3 tables and choosing newest logged entry per id

I got rather complicated riddle to solve. So far I'm unlocky.
I got 3 tables which I need to join to get the result.
Most important is that I need highest h_id per p_id. h_id is uniqe entry in log history. And I need newest one for given point (p_id -> num).
Apart from that I need ext and name as well.
history
+----------------+---------+--------+
| h_id | p_id | str_id |
+----------------+---------+--------+
| 1 | 1 | 11 |
| 2 | 5 | 15 |
| 3 | 5 | 23 |
| 4 | 1 | 62 |
+----------------+---------+--------+
point
+----------------+---------+
| p_id | num |
+----------------+---------+
| 1 | 4564 |
| 5 | 3453 |
+----------------+---------+
street
+----------------+---------+-------------+
| str_id | ext | name |
+----------------+---------+-------------+
| 15 | | Mein st. 33 | - bad name
| 11 | | eck st. 42 | - bad name
| 62 | abc | Main st. 33 |
| 23 | efg | Back st. 42 |
+----------------+---------+-------------+
EXPECTED RESULT
+----------------+---------+-------------+-----+
| num | ext | name |h_id |
+----------------+---------+-------------+-----+
| 3453 | efg | Back st. 42 | 3 |
| 4564 | abc | Main st. 33 | 4 |
+----------------+---------+-------------+-----+
I'm using Oracle SQL. Tried using query below but result is not true.
SELECT num, max(name), max(ext), MAX(h_id) maxm FROM history
INNER JOIN street on street.str_id = history._str_id
INNER JOIN point on point.p_id = history.p_id
GROUP BY point.num
In Oracle, you can use keep:
SELECT p.num,
MAX(h.h_id) as maxm,
MAX(s.name) KEEP (DENSE_RANK FIRST ORDER BY h.h_id DESC) as name,
MAX(s.ext) KEEP (DENSE_RANK FIRST ORDER BY h.h_id DESC) as ext
FROM history h INNER JOIN
street s
ON s.str_id = h._str_id INNER JOIN
point p
ON p.p_id = h.p_id
GROUP BY p.num;
The keep syntax allows you to do "first()" and "last()" for aggregations.

Get Data from two different tables on a condition

I got situation like below:
Posts and like tables are respectively:
----------------- --------------------------
| post_id | text | | post_id | like | person|
------------------- ---------------------------
| 1 | hello | | 1 | yes | Jhon |
| 2 | Haii | | 1 | yes | Sham |
| 3 | I am..| | 1 | yes | Ram |
-------------------- | 2 | yes | Mahe |
----------------------------
Now I want to get all posts and I want to know whether each post is liked by Sham or not.
So result will be:
-----------------------------------
| post_id | text | liked_by_Sham |
-----------------------------------
| 1 | hello | yes |
| 2 | Haii | no |
| 3 | I am | no |
------------------------------------
As I am new to SQL can anyone explain me how to do that. I tried it using Inner join but it doesn't work.
I tried with below query:
select posts.*,liketb.like
from posts
inner join liketb
on posts.post_id = liketb.post_id
where liketb.person = 'Sham';
This query is giving only posts liked by sham.
Use left join, with case. like is a keyword. Make sure it is properly escaped.
select p.post_id, p.text,
case when l.like = 'yes' then l.like else 'no' end as liked_by_sham
from posts p
left join liketb l on p.post_id = l.post_id and l.person = 'Sham';
Sql Fiddle Demo
You need put the filter clausule on the ON section to get all post with yes, no or null when no match. And use nvl to convert all NULL to 'no'
SELECT p."post_id", p."text", nvl(l."like", 'no') as liked_by_sham
FROM posts p
LEFT JOIN liketb l
ON p."post_id" = l."post_id"
AND l."person" = 'Sham'
OUTPUT
| post_id | text | LIKED_BY_SHAM |
|---------|--------|---------------|
| 1 | hello | yes |
| 3 | I am.. | no |
| 2 | Haii | no |

Distinct code wont work SQL Server

SELECT DISTINCT
U.Unit_ID, P.Plant_ID, P.Project_NR, U.Key_code_list,
S.Status_type, Kc.Key_codes4
FROM
Plant as P
INNER JOIN
Unit as U ON P.Plant_NR = U.Plant_NR
INNER JOIN
[dbo].[Key_code_list] as Kcl ON P.Project_NR = Kcl.Project_NR
INNER JOIN
Status_codes as S ON S.Status_nr = Kcl.Status
INNER JOIN
Key_codes as Kc ON Kc.Key_code_ID = Kcl.Key_code_list_ID
I have this code, and it will give me not the outcome I hoped for. I know it's probably something easy but I've been banging my head against the wall now for an hour and thought why not ask you guys.
The outcome now is:
Unit_ID | Plant_ID | Project_NR | Key_code_list | Status_type | Key_code_4 | Key_code _ID
-----------------------------------------------------------------------------------------------
MEOD | SM | 114015 | 4 | Assigned | AC49 | 11 |
MLO | SM | 114015 | 4 | Assigned | AC49 | 11 |
MEOD | SM | 114015 | 4 | Assigned | AC47 | 12 |
MLO | SM | 114015 | 4 | Assigned | AC47 | 12 |
The outcome is now twice as a result but that's not correct. I would love to get the answer just once. Can someone please help me?
The desired outcome is :
MEOD | SM | 114015 | 4 | Assigned | AC49 | 12 |
MLO | SM | 114015 | 4 | Assigned | AC47 | 11 |
SELECT * FROM dbo.Key_Code_List WHERE Project_NR = '114015'
Key_code_list | Status | Plant_ID | Textfield_unit | Unit_ID | Key_code_list_ID | Project_NR
4 | 2 | SM | NULL | MLO | 11 | 114015
4 | 2 | SM | NULL | MEOD | 12 | 114015
You are missing the Unit_ID field in the join to the Key_Code_List table.
SELECT DISTINCT
U.Unit_ID, P.Plant_ID, P.Project_NR, U.Key_code_list,
S.Status_type, Kc.Key_codes4
FROM
Plant as P
INNER JOIN
Unit as U ON P.Plant_NR = U.Plant_NR
INNER JOIN
[dbo].[Key_code_list] as Kcl ON
P.Project_NR = Kcl.Project_NR AND
U.Unit_ID = Kcl.Unit_ID -- add this to the JOIN condition
INNER JOIN
Status_codes as S ON S.Status_nr = Kcl.Status
INNER JOIN
Key_codes as Kc ON Kc.Key_code_ID = Kcl.Key_code_list_ID

Combining two view into one result set with transform?

I have a couple of views that generates the following two outputs in SQL Server.
First one (Flats output) shows the number of flats in a particular town with Tileroofs and Brickwalls. Second one shows the same, but for houses.
What I'm trying to do is to create a final table that looks like the 3rd example where the flats and house counts are combined with the corresponding Tileroof and Brickwall combinations.
I have tried union and then grouping, but I'm really struggling to get the Flats and Houses count columns side by side. Is anyone able to help please?
Thanks
--View one
| Town | Flats | TileRoofs | Brick Wall |
-----------------------------------------
| A | 3 | Y | N |
| A | 4 | N | Y |
| A | 8 | N | N |
--View two
| Town | Houses | TileRoofs | Brick Wall |
------------------------------------------
| A | 1 | Y | Y |
| A | 2 | Y | N |
| A | 5 | N | Y |
| A | 2 | N | N |
--Prefered output, by combining the two--
| Town | Flats | Houses | TileRoofs | Brick Wall |
--------------------------------------------------
| A | 0 | 1 | Y | Y |
| A | 3 | 2 | Y | N |
| A | 4 | 5 | N | Y |
| A | 8 | 2 | N | N |
Full outer join might help here.
select isnull(a.Town, b.Town) Town,
isnull(a.TileRoofs, b.TileRoofs) TileRoofs,
isnull(a.[Brick wall], b.[Brick wall]) [Brick wall],
isnull(a.Flats, 0) Flats,
isnull(b.Houses, 0) Houses
from ViewOne a
full outer join ViewTwo b
on a.Town = b.Town
and a.TileRoofs = b.TileRoofs
and a.[Brick wall] = b.[Brick wall]
select
v2.Town ,coalesce(v1.flat,0) as flat,v2.houses,v2.TileRoofs, v2.Brick, v2.Wall
from
view2 as v2 left join view1 as v1
on v1.town=v2.town
You may be after a full outer join
select
houses.town,
flats.flats,
houses.houses,
houses.BrickWall,
houses.TileRoofs
from flats
full outer join houses
on houses.town=flats.town
and houses.TileRoofs = flats.TileRoofs
and houses.BrickWall = flats.BrickWall

sql compact 3.5, select top n rows from each group

I am writing a query to select the top 1 record from each group. Keep in mind that I working on sql compact 3.5 and thus can not use the rank function. I'm pretty sure my query is incorrect but I'm not sure how to select top from each group. Any one got any ideas?
Here is the query I was trying to get working
/*
* added fH.InvoiceNumber to my query to get result further below.
/
select tH., t.CustomerNumber, c.CustomerName, fH.Status, fH.InvoiceNumber
from tenderHeader tH
join task t ON tH.TaskActivityID = t.ActivityID
join finalizeTicketHeader fH ON tH.FinalizeTicketTaskActivityID = fH.TaskActivityID
join customer c ON t.CustomerNumber = c.CustomerNumber
where fH.Status <> '3' AND t.TripID = '08ea6982-6efd-46fa-9753-0fd8b076f24c';
Here is what my tables look like:
customer table:
|------------------------------------------------|
| CustomerNumber | CustomerName | Address1 | ... |
|------------------------------------------------|
| 0012084737 | Customer A | 150 Rd A | ... |
|------------------------------------------------|
| 0012301891 | Customer B | 152 Rd A | ... |
|------------------------------------------------|
task table
|-----------------------------------------------------------------|
| ActivityID | TripID | TaskTypeName | Status | CustomerNumber |
|-----------------------------------------------------------------|
| 4967f6cc | 08ea6982 | Payment | 2 | 0012084737 |
|-----------------------------------------------------------------|
| e96469a1 | 08ea6982 | Payment | 2 | 0012301891 |
|-----------------------------------------------------------------|
finalizeTicketHeader table
|---------------------------------------------------|
| TaskActivityID | InvoiceNumber | Amount | Status |
|---------------------------------------------------|
| 916082c8 | 1000 | 563.32 | 3 |
|---------------------------------------------------|
| 916082c8 | 1001 | -343.68 | 0 |
|---------------------------------------------------|
| 4b38bf60 | 1002 | 152.29 | 0 |
|---------------------------------------------------|
| 4b38bf60 | 1003 | -35.80 | 0 |
|---------------------------------------------------|
tenderHeader table
|-------------------------------------------------------------------------------------|
| TaskActivityID | InvoiceNumber | PastDue | TodaysDue | FinalizeTicketTaskActivityID |
|-------------------------------------------------------------------------------------|
| 4967f6cc | 1234567891 | 23.55 | 219.64 | 916082c8 |
|-------------------------------------------------------------------------------------|
| e96469a1 | 1234567893 | 0.00 | 116.49 | 4b38bf60 |
|-------------------------------------------------------------------------------------|
the problem I was having was getting duplicates.
like so:
|------------------------------------------------------------------------------------------------------------------------------------|
| TaskActivityID | InvoiceNumber | PastDue | TodaysDue | FinalizeTicketTaskActivityID | CustomerNumber | CustomerName | InvoiceNumber |
|------------------------------------------------------------------------------------------------------------------------------------|
| 4967f6cc | 1234567891 | 23.55 | 219.64 | 916082c8 | 0012084737 | Customer A | 1001 |
|------------------------------------------------------------------------------------------------------------------------------------|
| e96469a1 | 1234567893 | 0.00 | 116.49 | 4b38bf60 | 0012301891 | Customer B | 1002 |
|------------------------------------------------------------------------------------------------------------------------------------|
| e96469a1 | 1234567893 | 0.00 | 116.49 | 4b38bf60 | 0012301891 | Customer B | 1003 |
|------------------------------------------------------------------------------------------------------------------------------------|
I've rewritten the query like so, but I need to get specific columns from the sub query.
select tH.* from tenderHeader th
inner join task t on tH.TaskActivityID = t.ActivityID
inner join (
select k.TaskActivityID from finalizeTicketHeader k group by k.TaskActivityID
) as fH on tH.FinalizeTicketTaskActivityID = fH.TaskActivityID
inner join customer c on t.CustomerNumber = c.CustomerNumber
I need to get the status from fH. Any ideas of how to do that?
select tH.*, fH.Status from tenderHeader th
inner join task t on tH.TaskActivityID = t.ActivityID
inner join finalizeTicketHeader fH on tH.FinalizeTicketTaskActivityID = tH.TaskActivityID
inner join customer c on t.CustomerNumber = c.CustomerNumber
where tH.FinalizeTicketTaskActivityID = (
select top (1) k.TaskActivityID from finalizeTicketHeader k
);
but it seems that sql compact 3.5 does not support scalar values with subquery in where cause.
Here is an example that demonstrat a way of selecting the top 1 from each group
id|time
--------
2 | 1:10
2 | 0:45
2 | 1:45
2 | 1:30
1 | 1:00
1 | 1:10
the table is called table_1; we group by id and assume that time should be desc ordered
select table_1.* from table_1
inner join (
select id, max(time) as max_time from table_1
group by id
) as t
on t.max_time = table_1.time and table_1.id = t.id
order by table_1.id
the result we get is
id|time
--------
1 | 1:10
2 | 1:45