I searched before asking my question:
I have two tables.
Table info:
no | name
1 | david
2 | kang
Table info_kill:
no | staffno | skillno
------------------------
1 | 1 | 1
2 | 2 | 1
3 | 2 | 2
4 | 2 | 3
staffno in info_skill table and no in info table is foreign key.
I want to get:
name contains 'ka'
have skillno 1, 2, 3.
so, this is my sql,
SELECT a.NAME
FROM (SELECT no,
NAME
FROM info
WHERE NAME LIKE '%ka%') AS a
INNER JOIN info_skill AS b
ON a.no = b.staffno
INNER JOIN info_skill AS c
ON a.no = c.staffno
INNER JOIN info_skill AS d
ON a.no = d.staffno
WHERE b.skillno = '1'
AND c.skillno = '2'
AND d.skillno = '3'
what I wonder is this part.
INNER JOIN info_skill AS b
ON a.no = b.staffno
INNER JOIN info_skill AS c
ON a.no = c.staffno
INNER JOIN info_skill AS d
ON a.no = d.staffno
WHERE b.skillno = '1'
AND c.skillno = '2'
AND d.skillno = '3'
Is there any other way?
Try this:
SELECT I.name
FROM info I
JOIN info_skill S
ON I.no = S.staffno
WHERE I.name LIKE'%ka%" AND
S.skillno=1 OR
S.skillno=2 OR
S.skillno=3
This means:
You join the two tables following the foreign key
Then you search for any name containing ka word using LIKE %ka%
Now, you need to check if skillno is equal to 1, 2 or 3
If this is not what you need exactly, then please make your question more clear by explaining what you are looking for exactly.
select a.name
from info a
inner join info_skill as b on a.no = b.staffno
where b.skillno in (1,2,3)
and name like '%ka%'
group by a.name
having count(distinct b.skillno) = 3
SQLFiddle demo
Related
SQL Server...
I need to Join tbl_B or tbl_C with tbl_A. Case tblA.id = 1 Join B or Case tblA.id = 2 Join C
let's say this example:
Table: tblFood
Id_Food | Fk_Id_Foodtype
1 | 1
1 | 2
Table: tabVegetable
Id | Mame |Color
1 | eggplant |black
Table: tabFrute
Id | Name |Color
1 | apple |red
On the table tblFood above...
if Fk_Id_Foodtype = 1 join Id_Food on tabVegetable
if Fk_Id_Foodtype = 2 join Id_Food on tabFrute
So I can return execute a select like this: SELECT tblFood.Id_Food, (tabVegetable or tabFrute).name, (tabVegetable or tabFrute).color
Note: I only have tblFruts and tblVegetable, so I always check these two option.
Thank you!
Join to tblFood the other tables with LEFT joins and in the ON clauses specify the condition for Fk_Id_Foodtype.
In the SELECT list of columns use COALESCE() to get the values of the columns from each table:
SELECT f.*,
COALESCE(v.Name, fr.Name) Name,
COALESCE(v.Color, fr.Color) Color
FROM tblFood f
LEFT JOIN tabVegetable v ON f.Fk_Id_Foodtype = 1 AND v.Id = f.Id
LEFT JOIN tabFrute fr ON f.Fk_Id_Foodtype = 2 AND fr.Id = f.Id
I'm currently struggling with carrying out some joins and hoping someone can shed some light on this.
I have three tables: A,B,C
Table C lists names of individuals
Table A lists the food they like to eat
Table B is the link to show what food in A a person likes from C (Our
system was built without foreign keys! I know, it's a pain!)
What I'm trying to write is a query that will return a list of values from Table C which shows the individuals that don't like a specific food...say PFC
I have the following:
select * from table_c c
inner join table_b b
on c.name = b.bValue
inner join table_a a
on b.aValue = a.number
where a.value not in('PFC')
I'm assuming the joins are working but as table A has multiple values, the two extra rows are being returned. Is it possible to not show this client if one of the joins shows a food I don't want to see?
Table A
|---------------------|------------------|
| Number | Value |
|---------------------|------------------|
| 1 | McDs |
|---------------------|------------------|
| 1 | KFC |
|---------------------|------------------|
| 1 | PFC |
|---------------------|------------------|
Table B
|---------------------|------------------|
| bValue | aValue |
|---------------------|------------------|
| John | 1 |
|---------------------|------------------|
Table C
|---------------------|
| Name |
|---------------------|
| John |
|---------------------|
I'm also using SQL Server 2013 if that makes a difference!
With NOT EXISTS:
select * from table_c c
where not exists (
select 1 from table_b b inner join table_a a
on b.aValue = a.number
where b.bValue = c.name and a.value = 'PFC'
)
One option is to aggregate by name:
SELECT
c.Name
FROM table_c c
INNER JOIN table_b b
ON c.Name = b.bValue
INNER JOIN table_a a
ON b.aValue = a.Number
GROUP BY
c.Name
HAVING
COUNT(CASE WHEN a.Value = 'PFC' THEN 1 END) = 0;
We could also try expressing this using an exists query:
SELECT
c.Name
FROM table_c c
WHERE NOT EXISTS (SELECT 1 FROM table_b b
INNER JOIN table_a a
ON b.aValue = a.Number
WHERE c.Name = b.bValue AND
a.Value = 'PFC');
The scenario is as follows: I have these two tables:
(TABLE1)
SUPER_ID| NAME |
-------+--
1 | BOB |
(TABLE2)
ID| SUPER_ID |
-------+----+
1 | 1 |
2 | 1 |
3 | 1 |
If I join these two tables as
`SELECT a.super_id, a.name
FROM TABLE1 a LEFT OUTER JOIN TABLE2 b ON a.super_id = b.super_id
WHERE a.super_id = 1`
The result will be
SUPER_ID| NAME |
-------+--------
1 | BOB |
1 | BOB |
1 | BOB |
How can I select only the rows from TABLE1 without using a GROUP BY? Thanks
UPDATE: Ok, so I have a 3rd table...
(TABLE3)
ID| TYPE |
-------+----+
1 | A |
2 | B |
3 | C |
which I need to Join to TABLE2 AS:
SELECT a.super_id, a.name
FROM TABLE1 a INNER JOIN
TABLE2 b ON a.super_id = b.super_id INNER JOIN
TABLE3 c ON b.id = c.id
WHERE a.super_id = 1
by restricting the join based on some other [unique] criterion. And the SQL syntax of course depends on what other criterion you choose. Say you want the latest record entered, If the table has a timestamp column you could do this:
SELECT a.super_id, a.name
FrOM TABLE1 a LEFT JOIN TABLE2 b
ON b.super_id = a.super_id
and b.timestamp = (Select Max(timestamp)
From TABLE2
Where super_id = a.super_id)
WHERE a.super_id = 1
If you don't have a timestamp, but you have a unique index or key (looks like id is such), you could use that:
SELECT a.super_id, a.name
FrOM TABLE1 a LEFT JOIN TABLE2 b
ON b.super_id = a.super_id
and b.id= (Select Max(id)
From TABLE2
Where super_id = a.super_id)
WHERE a.super_id = 1
There are many ways to do it.
I assume you want rows from table1 if you have super_id in table2.
You can use EXISTS
SELECT a.super_id, a.name
FROM TABLE1 a
WHERE EXISTS ( SELECT NULL FROM table2 b WHERE a.super_id = b.super_id )
AND a.super_id = 1
UPDATE
You can use GROUP BY into a WITH clause.
WITH single_b AS ( SELECT super_id, name
FROM table2
GROUP BY super_id, name )
SELECT a.super_id, a.name
FROM TABLE1 a INNER JOIN single_b b ON a.super_id = b.super_id
INNER JOIN TABLE3 c ON b.super_id = c.id
WHERE a.super_id = 1
I am having problem with sql join (oracle/ms sql)
I have two tables
A
ID | B_ID
---|------
1 | 1
1 | 4
2 | 3
2 | 2
----------
B
B_ID | B_VA| B_VB
-------|--------|-------
1 | 1 | a
2 | 2 | b
3 | 5 | c
4 | 2 | d
-----------------------
From these two tables I need A.ID, B.B_ID, B.B_VA (MAX), B.B_VB (with max B.B_VA)
So result table would be like
ID | B_ID | B_VA| B_VB
-------|--------|--------|-------
1 | 4 | 2 | d
2 | 3 | 5 | c
I tried some joins without success. Can anyone help me with query to get the result I want.
Thank you
Your logic as described doesn't quite correspond to the data. For instance, b_va is numeric, but the column in the output is a string.
Perhaps you want this. The data in a to be aggregated to get the maximum b_id value. Then each column to be joined to get the corresponding b_vb column. That, at least, conforms to your desired output:
select a.id, a.b_id, b1.b_vb as b_va, b2.b_vb
from (select id, max(b_id) as b_id
from a
group by id
) a join
b b1
on a.id = b1.b_id join
b b2
on a.b_id = b2.b_id;
EDIT:
For the corrected data, I think this is what you want:
select a.id, a.b_id, max(b1.b_va) as b_va, b2.b_vb
from (select id, max(b_id) as b_id
from a
group by id
) a join
b b1
on a.id = b1.b_id join
b b2
on a.b_id = b2.b_id
group by a.id, a.b_id, b2.b_vb;
Try this
SELECT X.ID, Y.B_ID, X.B_VA, Y.B_VB
FROM (SELECT A.ID, MAX(B_VA) AS B_VA
FROM A INNER JOIN B ON A.B_ID = B.B_ID
GROUP BY A.ID) AS X INNER JOIN
A AS Z ON X.ID = Z.ID INNER JOIN
B AS Y ON Z.B_ID=Y.B_ID AND X.B_VA=Y.B_VA
I have a database table that has the following structure:
TABLE_A
DOC_ID | STATUS
1 | 0
2 | 1
TABLE_B
PK_ID | DOC_ID | NAME | VALUE
1 | 1 | A | 1
2 | 1 | B | 2
3 | 2 | A | 1
4 | 2 | B | 1
5 | 2 | C | 1
DOC_ID is the FOREIGN KEY on TABLE_B.
Then I create a VIEW so that I may more easily sort on NAME.
CREATE VIEW [dbo].[V_MY_VIEW] AS
SELECT a.DOC_ID, a1.VALUE AS 'A', a2.VALUE AS 'B', a3.VALUES AS 'C'
FROM dbo.TABLE_A a,
( SELECT DOC_ID, VALUE FROM dbo.TABLE_B WHERE NAME = 'A') a1
LEFT OUTER JOIN ( SELECT DOC_ID, VALUE FROM dbo.TABLE_B WHERE NAME = 'B') a2
ON a1.DOC_ID = a2.DOC_ID
LEFT OUTER JOIN ( SELECT DOC_ID, VALUE FROM dbo.TABLE_B WHERE NAME = 'C') a3
ON a1.DOC_ID = a3.DOC_ID
WHERE a.STATUS IN (0, 1)
This view will only include the rows with DOC_ID = 2 since the rows with DOC_ID = 1 do not have a row with NAME = C. How should I modify the VIEW so that it will include all the rows from TABLE_B?
Thanks.
CREATE VIEW [dbo].[V_MY_VIEW] AS
SELECT a.DOC_ID, a1.VALUE AS A, a2.VALUE AS B, a3.VALUE AS C
FROM dbo.TABLE_A a
LEFT JOIN (SELECT DOC_ID, VALUE FROM dbo.TABLE_B WHERE NAME = 'A') a1
ON a.DOC_ID = a1.DOC_ID
LEFT OUTER JOIN ( SELECT DOC_ID, VALUE FROM dbo.TABLE_B WHERE NAME = 'B') a2
ON a.DOC_ID = a2.DOC_ID
LEFT OUTER JOIN ( SELECT DOC_ID, VALUE FROM dbo.TABLE_B WHERE NAME = 'C') a3
ON a.DOC_ID = a3.DOC_ID
WHERE a.STATUS IN (0, 1)
Look the results at http://sqlfiddle.com/#!3/5574b/4/0
SELECT * FROM TABLE_A LEFT OUTER JOIN TABLE_B ON TABLE_A.DOC_ID = TABLE_B.DOC_ID
WHERE TABLE_A.STATUS IN (0, 1)
Replace * with the columns you want to display.
Include an ISNULL(Name, ) in your order by clause unless you want none matches at the top.