SQL Join Including NULLs - sql-server

Using SQL Server Management Studio 2016 (v 13.0).
I have two tables with two distinct keys I can use to join, with the catch being that there are mixed NULLs in both PK columns:
Table 1 Table 2
Acct1 App1 Acct2 App2 Product
----------- ----------------------
1 A NULL A Bed
2 B 2 B Sofa
3 C 3 NULL Bed
4 D 4 D Bed
Desired result in the joined table, only including those where Product = Bed:
Acct App Product
1 A Bed
3 C Bed
4 D Bed
Thank you!

While I agree #d219's answer should be the correct solution, a different approach could use an or in the join such like:
select Acct1,App1,Product
from table1 inner join table2
on App1=App2 or Acct1=Acct2
where Product='Bed'
See this post for discussion on using the or join.

One way would be to do two separate SELECT statements using each key and then UNION them, something like this:
SELECT t1.Acct1, t1.App1, t2.Product
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.Acct1 = t2.Acct2
WHERE t2.Product = 'Bed'
UNION
SELECT t1.Acct1, t1.App1, t2.Product
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.App1 = t2.App2
WHERE t2.Product = 'Bed'

Related

How to use multi-column sql query result as input for new query

An alternative title would be "how to join two external tables with two different values, by row, from query result". I'm open to suggestions/edits.
I have this query result (2 of 6000+ lines shown)
objectpriref packpriref locpriref
------------ ---------- ----------
30889 229 16672
30990 267 16697
and 2 tables like this
objname location
id name id name
---------.-------- ---------.----
30889 MACQ_001 16672 A16
30890 BLAH_002 16673 A17
30990 FOOH_009 16697 B300
The desired result should look something like this
objectpriref objname locname
------------ ---------- ----------
30889 MACQ_001 A16
30990 FOOH_009 B300
If this can be done within SQL, what would be the best approach? What I've tried so far:
Put the query result into a temp table using INTO #mtt (for MyTempTable) from here and then trying to address the various columns as #mtt.objectpriref etc. This gets me invalid object name #mtt. This might deserve a separate question.
Put the query inside another select, but that runs into this, using IN works on single columns only.
I may be using the wrong keywords to google for. Any suggestions?
Something like
select
T1.objectpriref,
T2.name as objname,
T3.name as locname
from
table1 T1
inner join table2 T2
on T2.objnameid = T1.objectpriref
inner join table3 T3
on T3.locationid = T1.locpriref
Try this with your table names.
select t1.objectpreiref, t2.name, t3.name
from table1 t1
left join table2 t2 on t1.objectpriref = t2.objnameid
left join table3 t3 on t1.locpriref = t3.locationid

How to Left Inner Join two queries in Sybase?

I have two queries that should be joined together. Here is my query 1:
SELECT
t1.rec_id,
t1.category,
t1.name,
t1.code,
CASE
WHEN t1.name= 'A' THEN SUM(t1.amount)
WHEN t1.name = 'D' THEN SUM(t1.amount)
WHEN t1.name = 'H' THEN SUM(t1.amount)
WHEN t1.name = 'J' THEN SUM(t1.amount)
END AS Amount
FROM Table1 t1
GROUP BY t1.name, t1.rec_id, t1.category, t1.code
Query 1 produce this set of results:
Rec ID Category Name Code Amount
1 1 A MIX 70927.00
1 3 D MIX 19922.00
1 2 H MIX 55104.00
1 4 J MIX 76938.00
Then I have query 2:
SELECT
CASE
WHEN t2.category_id = 1 THEN SUM(t2.sum)
WHEN t2.category_id = 2 THEN SUM(t2.sum)
WHEN t2.category_id = 3 THEN SUM(t2.sum)
WHEN t2.category_id = 4 THEN SUM(t2.sum)
END AS TotalSum
FROM Table2 t2
INNER JOIN Table1 t1
ON t1.amnt_id = t2.amnt_id
AND t2.unique_id = #unique_id
GROUP BY t2.category_id
The result set of query 2 is this:
TotalSum
186013.00
47875.00
12136.00
974602.00
All I need is this result set that combines query 1 and query 2:
Rec ID Category Name Code Amount TotalSum
1 1 A MIX 70927.00 186013.00
1 3 D MIX 19922.00 47875.00
1 2 H MIX 55104.00 12136.00
1 4 J MIX 76938.00 974602.00
As you can see there is connection between table 1 and table 2. That connection is amnt_id. However, I tried doing LEFT INNER JOIN on query 1 and then simply using same logic with case statement to get the total sum for table 2. Unfortunately Sybase version that I use does not support Left Inner Join. I'm wondering if there is other way to join these two queries? Thank you
I wondered if the CASE statement makes sense in the first query because it sums in every row. Are there other values for the name column except A, D, H, J? If not you can change the CASE statement to SUM(t1.amount) AS Amount. Also the GROUP BY in the first query seems dubious to me: you are grouping by the record id column - that means you are not grouping at all but instead return every row. If that is what you really want you can omit the SUM at all and just return the pure amount column.
As far as I understood your problem and your data structure: the values in Table2 are kind of category sums and the values in Table1 are subsets. You would like to see the category sum for every category in Table1 next to the single amounts?
You would typically use a CTE (common table expression, "WITH clause") but ASE doesn't support CTEs, so we have to work with joins. I recreated your tables in my SQL Anywhere database and put together this example. In a nutshell: both queries are subqueries in an outer query and are left joined on the category id:
SELECT *
FROM
(
SELECT
t1.rec_id,
t1.category,
t1.name,
t1.code,
CASE
WHEN t1.name= 'A' THEN SUM(t1.amount)
WHEN t1.name = 'D' THEN SUM(t1.amount)
WHEN t1.name = 'H' THEN SUM(t1.amount)
WHEN t1.name = 'J' THEN SUM(t1.amount)
END AS Amount
FROM Table1 t1
GROUP BY t1.rec_id, t1.name, t1.category, t1.code
) AS t1
LEFT JOIN
(
SELECT category_id, SUM(sum) FROM
table2
GROUP BY category_id
) AS totals(category_id, total_sum)
ON totals.category_id = t1.category;
This query gives me:
Rec ID Category Name Code Amount Category_id total_sum
2 3 D MIX 19922.00 3 47875.00
3 2 H MIX 55104.00 2 12136.00
1 1 A MIX 70927.00 1 186013.00
4 4 J MIX 76938.00 4 974602.00
You surely have to tweak it a bit including your t2.unique_id column (that I don't understand from your queries) but this is a practical way to work around ASE's missing CTE feature.
BTW: it's either an INNER JOIN (only the corresponding records from both tables) or a LEFT (OUTER) JOIN (all from the left, only the corresponding records from the right table) but a LEFT INNER JOIN makes no sense.

Create and execute stored procedure in SQL Server

I have four tables:
dbo.Projects (id, ProjectName, Areas, PaymentSystem, Districts.id, purpose.id, types.id, etc)
dbo.Districts(id, DistrictsName)
dbo.Purpose (id, PurposeName) - has residential & commercial
dbo.Types (id, typName)
I want to select DistrictsName where PurposeName = 'residential'
I tried this procedure :
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'
this is the result from this procedure:
ID DistrictsName PurposeName
1 District1 residential
2 District1 residential
3 District2 residential
4 District2 residential
i want display the DistrictsName without duplicate or with different values , i a have also one more project per district in projects records . this what i want to display :
ID DistrictsName PurposeName
1 District1 residential
2 District2 residential
how i get this result ,
any help is appreciated.
Why do people use stored procedures when views are much more appropriate? I have never understood this. It seems peculiar to SQL Server users.
In any case, you can do what you want with aggregation:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as id,
d.DistrictName, p.PurposeName
FROM dbo.Projects pr INNER JOIN
dbo.Purpose pu
ON pr.PurposeID = pu.ID INNER JOIN
dbo.Districts d
ON pr.DistrictID = d.ID
WHERE pu.PurposeName = N'Residential'
GROUP BY d.DistrictName, p.PurposeName;
The use of table aliases makes the query much easier to write and to read.
In addition, I don't understand the id column being output. Why would you want to construct a new id? In any case, that is what your data suggests.
Use DISTINCT statement for removing the duplicates:
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT DISTINCT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'

SQL Server date_format in join

I have two tables with two formats date
table 1 :
id time ref
5 1397635972 A
10 1397635975 B
50 1397635976 C
table 2 :
id time ref
10 2013/10/05 D
51 2014/01/02 E
how join two table on table1.id=table2.id and table1.time=table2.time
This is my attempt :
$sql=' select table1.id, table1.time, table1.ref, table2.id, table2.time, table2.ref
from table1 INNER JOIN table2
ON (table1.id = table2.id AND DATE_FORMAT(table1.time,'%y/%m/%d') = table2.time)';
Try this:
select table1.id, table1.time, table1.ref, table2.id, table2.time, table2.ref
from table1 INNER JOIN table2
ON (table1.id = table2.id AND FROM_UNIXTIME(table1.time) = table2.time)
Are you sure that the ID needs to be a part of the join as well? This kind of join with this kind of structure would make almost no sense from a database design standpoint...
No data are not shown
For example FROM_UNIXTIME table2.time :
SELECT FROM_UNIXTIME(1196440219) : '2007-11-30 10:30:19'
I need to format then become : 2013/10/05

How to use + in sql sever

I am trying to write a join query. Table A has a Primary Key = 123456000000 and table B has foreign key = 123456.
I want to know how can i join the 2 tables using inner join using + in query
I wrote the following -
SELECT RAP.COL1, FRE.COL2 FROM Table 1 AS RAP
INNER JOIN Table 2 AS FRE
ON RAP.COL1+'000000' = FRE.COL2
NOTE - COL2 = 123456000000
COL1 = 123456
I NEED TO ADD 000000 so that i can join. BUT THE ABOVE WRITTEN DOES NOT WORK :(
Please help
Cheers
OZ
Try this, but why the keys are different. Any specific reason.
SELECT RAP.COL1, FRE.COL2 FROM Table 1 AS RAP
INNER JOIN Table 2 AS FRE
ON (Convert(varchar(20),RAP.COL1)+'000000')as COL1 = FRE.COL2
SELECT RAP.COL1, FRE.COL2 FROM Table 1 AS RAP
INNER JOIN Table 2 AS FRE
ON RAP.COL1 = LEFT(FRE.COL2,6)

Resources