How do show a result table from two 'select'? SQL - sql

I have 2 queries:
First query:
select TableB.name, count(TableB.name) from TableB group by TableB.name
result:
name | count
Jack | 2
Marry| 1
and
Second query:
select DISTINCT TableA.kName, TableA.Value from TableA inner join TableB
ON
TableA.kName=TableB.name
result:
kName | Value
Jack | 1
Marry | 3
But I need result table:
kName | Value | newColumn
Jack | 1 | 2
Marry | 3 | 1
where the newColumn is result of first query, How can to do it? help, please.
maybe:
select DISTINCT TableA.kName, TableA.value,
(select TableB.name, count(TableB.name) from TableB group by TableB.name)
AS
newColumn from TableA inner join TableB ON TableA.kName=TableB.name
but this is not work :(

Try this query
SELECT tableB.name, tableA.value, count(tableB.name) as newColum FROM tableB
JOIN tableA ON tableB.name = tableA.kname
GROUP BY tableB.name,tableA.value

select kname, value, "newColumn"
from
(
select name, count(name) as "newColumn"
from tb
group by name
) tb
inner join
(
select distinct kname, value
from ta
) ta ta.kname = tb.name

Related

select the next order of data in tableB using current data in tableA

I have two tables: tableA and tableB
tableA
------------------------------
| CD | stg_cd |
------------------------------
| APDN_82 | CUSC |
| APDN_82 | CUC |
------------------------------
tableB
------------------------------
| stg_cd | srt_ordr |
------------------------------
| CUSC | 1 |
| KLD | 3 |
| CUC | 2 |
------------------------------
I am trying to select the next order of data(i.e CUC) in tableB using current data(i.e CUSC) in tableA
My Expected result should be like
------------------------------
| CD | stg_cd |
------------------------------
| APDN_82 | CUC |
------------------------------
This is what i tried
(SELECT * FROM tableA AS A
WHERE A.ID = 'APDN_82' AND A.stg_cd
IN (SELECT lead('CUSC') over (order by B.srt_ordr) from tableB AS B)
But here i got a error : 'lead' is not a recognized built-in function name.
I tried to change the compatibility level to 110, but i did not had permission to change it.
Is there any other way to do without using lead ?
this will work:
select n.* from tableA n,(select * from tableB where srt_ordr=(select srt_ordr from
tableB where stg_cd='CUSC')+1)m
where
n.stg_cd=m.stg_cd
You can do like
SELECT CD,
stg_cd2
FROM
T1 JOIN
(
SELECT TB1.stg_cd stg_cd1,
TB1.srt_ordr srt_ordr1,
TB2.stg_cd stg_cd2,
TB2.srt_ordr srt_ordr2
FROM T2 TB1 JOIN T2 TB2
ON TB1.srt_ordr + 1 = TB2.srt_ordr
) TT
ON T1.stg_cd = TT.stg_cd1
WHERE T1.stg_cd = 'CUSC'
Demo
You probably need to partition by tablea.CD and find next row per partition. You can use ROW_NUMBER() for this:
SELECT *
FROM (
SELECT tablea.*, ROW_NUMBER() OVER (PARTITION BY tablea.CD ORDER BY tableb.srt_ordr) AS rn
FROM tablea
INNER JOIN tableb ON tablea.stg_cd = tableb.stg_cd
WHERE tableb.srt_ordr > (SELECT srt_ordr FROM tableb WHERE stg_cd = 'CUSC')
)
AS x
WHERE rn = 1
Demo on DB<>Fiddle
Or you could use correlated sub query:
SELECT *
FROM tablea
WHERE stg_cd = (
SELECT TOP 1 stg_cd
FROM tableb
WHERE stg_cd IN (
SELECT stg_cd
FROM tablea AS x
WHERE x.CD = tablea.CD
)
AND srt_ordr > (
SELECT srt_ordr
FROM tableb
WHERE stg_cd = 'CUSC'
)
)
Demo on DB<>Fiddle
I Would write it this way:
SELECT *
FROM TABLEA AS A
WHERE A.ID = 'APDN_82'
AND A.STG_CD IN (SELECT STG_CD
FROM TABLEB
WHERE SRT_ORDR IN (SELECT B.SRT_ORDR + 1
FROM TABLEB AS B
WHERE B.STG_CD = 'CUSC'
)
)

Only use data from TableA when TableB has no matching entry

So i have:
Table A with (not only Name - Multiple Columns):
| IDA | Name |
|:-----------|------------:|
| 1 | John |
| 2 | Jonas |
| 3 | Carl |
| 4 | Foo |
| 5 | Bar |
| 6 | Dog |
Table B with (not only Name - Multiple Columns):
| IDB | Name |
|:-----------|------------:|
| 1 | Bob |
| 2 | Lisa |
Table MAIN with:
| ID | FKtoB | FKtoA |
|:-----------|------------:|------------:|
| 1 | 1 | 4 |
| 2 | | 3 |
| 3 | | 1 |
| 4 | 2 | 6 |
| 5 | | 2 |
| 6 | | 5 |
My goal is to select from MAIN and prefer to use the data of Table B but if not Available i will use the data of Table A. I tryed to use coalesce but that didn't help because i dont want to mix the data, so if for example Table B has the data for one row, then in this row there should be no data from Table A.
My Query looks like that:
select
coalesce(b.name, a.name) as surname, coalesce(b.surname, a.surname) as surname
from MAIN m
left join TableA a on a.IDA = m.FKtoA
left join TableB b on b.IDA = m.FKtoB
My Problem there is that if for example b.name is filled and b.surname isn't it would mix b.name with a.surname, thats not okay in my case.
Maybe you could add the non-existens of b as join criteria:
select
coalesce(b.name, a.name) as name, coalesce(b.surname, a.surname) as surname
from MAIN m
left join TableB b on b.IDA = m.FKtoB
left join TableA a on a.IDA = m.FKtoA and b.IDA is null
EDIT: corrected one surname to name
Try Left Join with Case -
SELECT
M.ID, (CASE WHEN B.IDB IS NOT NULL THEN B.Name ELSE A.Name END) AS NAME
FROM
MAIN AS M
LEFT JOIN TableB as B ON B.IDB = M.FKtoB
LEFT JOIN TableA as A ON A.IDA = M.FKtoA
From SQL Server 2012 (and higher) you can use IIF:
SELECT
IIF(m.FKtoB IS NULL, A.name, B.name) AS surname
FROM MAIN m
LEFT JOIN TableA a ON a.IDA = m.FKtoA
LEFT JOIN TableB b ON b.IDA = m.FKtoB
try this:
declare #tableA table(IDA INT,Name varchar(MAX))
declare #tableB table(IDB INT, Name VARCHAR(MAX))
declare #tableMain table(ID INT,FKtoB INT,FKtoA INT)
INSERT INTO #tableA
SELECT 1,'John'
union all
SELECT 2, 'Jonas'
union all
SELECT 3, 'Carl'
union all
SELECT 4,'Foo'
union all
SELECT 5 ,'Bar'
union all
SELECT 6,'Dog'
INSERT INTO #tableB
SELECT 1, 'Bob'
Union all
SELECT 2, 'Lisa'
INSERT INTO #tableMain
SELECT 1,1,4
union all
SELECT 2,null,3
union all
SELECT 3,null,1
union all
SELECT 4,2,6
union all
SELECT 5,null,2
union all
SELECT 6,null,5
Select tm.Id,ISNULL(tb.Name,ta.Name) As NAME from #tableMain tm
LEFT JOIN #tableB tb on tm.FktoB=tb.IDb and IDb is not NUll
LEFT JOIN #tableA tA on tm.FktoA=ta.IDA and FktoB is NUll
You want to select from table A only when there is no match in table B, so given foreign keys are intact:
select
coalesce(b.firstname, a.firstname) as firstname,
coalesce(b.surname, a.surname) as surname,
coalesce(b.birthday, a.birthday) as birthday,
...
from MAIN m
left join TableB b on b.IDB = m.FKtoB
left join TableA a on a.IDA = m.FKtoA and m.FKtoB is null;
Another approach would be union all:
select firstname, surname, birthday, ...
from TableB
where IDB in (select FKtoB from MAIN)
union all
select firstname, surname, birthday, ...
from TableA
where IDA in (select FKtoA from MAIN where FKtoB is null);
Try this. It will give result as you want.
(select ida as ID ,
case when ida is not null then ida end fkToIda,
case when idb is not null then idb end fkToIdB
from A
left outer join B on a.ida=b.idb)
union
(select idb ,
case when ida is not null then ida end,
case when idb is not null then idb end
from A
right outer join B on a.ida=b.idb)

Get column name from one table by id in another table

I have 2 tables
Table 1:
Query_code | Item_code | Column_Name
2 | 1 | CN1
2 | 2 | CN2
2 | 3 | CN3
Table 2:
Query_code | Source_item| dest_item | pair_code
2 | 1 | 2 | 1
2 | 2 | 3 | 2
What i want to achive is to get source_item-dest_item as result.
According to data that will be:
CN1-CN2
CN2-CN3
What i tried is:
SELECT A.Column_Name
FROM TABLE1 A inner join
TABLE2 B
ON A.QUERY_CODE=B.QUERY_CODE
But this is not even close to my goal
What you need to do is use TABLE2 to identify the source_item and dest_item, then join with TABLE1 the first time to replace source_item with the column name, and join again with TABLE1 to replace dest_item with the other column name.
SELECT A.Column_Name, B.Column_Name
FROM t2 C
LEFT JOIN t1 A
ON C.Source_item=A.Item_code
LEFT JOIN t1 B
ON C.Dest_item=B.Item_code
WHERE C.Query_code=A.Query_code
AND C.Query_code=B.Query_code
Running Example on SQLFiddle
This should work. It is unclear what your Query_Code is meant to do, so I omitted it from the query.
EDIT Inserted Query_code condition as well.
SELECT
Source.Column_Name || '-' || Dest.Column_Name AS ResultPair
FROM
TABLE2 B
INNER JOIN TABLE1 Source
ON B.source_item = Source.item_code AND B.Query_code = Source.Query_code
INNER JOIN TABLE1 Dest
ON B.dest_item = Dest.item_code AND B.Query_code = Dest.Query_code;
Here you go
WITH table1 (query_code, item_code ,column_name ) AS
(SELECT 2,1,'cn1' UNION ALL
SELECT 2,2,'cn2' UNION ALL
SELECT 2,3,'cn3'),
table2 (query_code , source_item, dest_item , pair_code) AS
(SELECT 2,1,2,1 UNION ALL
SELECT 2,2,3,2)
SELECT a.column_name || '-' || c.column_name
FROM table1 a
INNER JOIN table2 b ON a.item_code=b.source_item
INNER JOIN table1 c ON c.item_code=b.dest_item;

Postgresql tables intersect

I have a two tables in my postgresql database.
Both tables have same columns.
How can i prefer values from tableA which are not null?
TableA
id | name
1 | val_a_1
2 | val_a_2
3 | (null)
TableB
id | name
1 | (null)
2 | val_b_2
3 | val_b_3
Result which i want to get:
id | name
1 | val_a_1
2 | val_a_2
3 | val_b_3
For now I've got it like this, but its more complicated, because there are lots of columns.
SELECT *
CASE
WHEN TableA.name is NULL or TableA.name = ''
THEN (SELECT TableB.name FROM TableB where TableB.id = 1)
ELSE TableA.name
END
AS name,
CASE
.
. another columns
.
END
Thanks
why not use COALESCE? Assuming all recordID in tableA is present on Table2
SELECT a.ID,
COALESCE(a.name, b.name) AS "Name"
FROM TableA a
INNER JOIN TableB b
ON a.ID = b.ID
SQLFIddle Demo
Conditional Expressions
The COALESCE function returns the first of its arguments (there can be more arguments) that is not null.
It's all about the COALESCE, not the join itself.
you can use a full outer join for the values which exist in tableA but not in tableB and vice versa:
select coalesce(tableA.ID, tableB.ID) as ID,
coalesce(tableA.Name, tableB.Name) as Name
from tableA full outer join tableB on tableA.ID = tableB.ID

IF ( Count(*) > 1)

I am trying to look through two tables TableA and TableB get print out the TableA.ID of any that show more than 1 count. TableA looks like this:
ID | Code
------------
1 | A
2 | B
3 | C
Table B Looks like
ID | AID | EffectiveDate | ExpirationDate
------------------------------------------------
1 | 1 | 2012-01-01 | 2012-12-31
2 | 1 | 2012-01-01 | 2012-12-31
3 | 2 | 2012-01-01 | 2012-12-31
4 | 3 | 2012-01-01 | 2012-12-31
The Query I am using looks like this:
DECLARE #MoreThanOne varchar(250)
SET #MoreThanOne = ''
IF((SELECT COUNT(*) FROM TableA
WHERE EXISTS(
SELECT TableB.ID
,TableB.EffectiveDate
,TableB.ExpirationDate
FROM TableB
WHERE TableB.AID = TableA.ID
and GETDATE() Between TableB.EffectiveDate and TableB.ExpirationDate
)
GROUP BY TableA.Code) > 1)
BEGIN
--SET #MoreThanOne = #MoreThanOne + TableA.Code + CHAR(10)
END
PRINT #MoreThanOne
I know that my nested Query works when reworked it will print the counts for all in the unique codes in TableA.
I know that I can not use what I commented out because i don't have access to TableA.Code.
My question is there another way to do this or how can I get access to TableA.Code for the Message MoreThanOne.
Thanks For the help!
This query will get you the codes for all AIDs that are duplicated in table B:
SELECT Code
FROM TableA
WHERE AID IN
(
SELECT AID
FROM TableB
GROUP BY AID
HAVING COUNT(*) > 1
)
You may also wish to add the WHERE condition that have in your stored procedure to the inner select.
Try this
SELECT TableA.ID, TableA.Code, Count(*) As Cnt
FROM TableB, TableA
WHERE TableB.AID = TableA.ID
and GETDATE() Between TableB.EffectiveDate and TableB.ExpirationDate
GROUP BY TableA.ID, TableA.Code
HAVING COUNT(*) > 1
You can do this very simply, with no join:
SELECT tableb.AID
FROM TableB
WHERE GETDATE() Between TableB.EffectiveDate and TableB.ExpirationDate
group by tableb.AID
having count(*) > 1
This simply aggregates tableB by AID, returning the values with more than one record. You only need to join to TableA if you want the code as well.
This should do you:
select Code = a.Code ,
Frequency = count(*)
from table_a a
join table_b b on b.aid = a.id
and current_timestamp between b.EffectiveDate and b.ExpirationDate
group by a.Code
having count(*) > 1
order by 2 desc -- order in descending sequence by frequency
1 -- then ascending sequence by code