SQL join based on select as column name - sql

So in one table I can use a replace and charindex to extract a specific ID that relates to a PK in another table, I want to then join the data from the other table based on the trimmed value, how can I do this?
select top 100 *, Replace(Left(LogValue,Charindex(';', LogValue) - 1) ,'RtaId=', '') as TaskID, PrmRoutingTask.*
from SytLog
inner join PrmRoutingTask on RtaId = TaskID
where LogTableName like '%Routing%' and LogValue like '%RtaAniId=397%'
order by 5 desc;
The problem I get is that the temp column name I create (TaskID) is not working in the inner join where in fact the results of TaskID have the reference to the RtaId in the RoutingTask table.

Assuming LogValue belongs to the first table you can use the column named TaskID if you produce a subquery as a table expression of the main query.
For example you can produce the column in the table expression a by doing:
select top 100
a.*,
PrmRoutingTask.*
from (
select *,
Replace(Left(LogValue,Charindex(';', LogValue) - 1) ,'RtaId=', '') as TaskID
from SytLog
) a
inner join PrmRoutingTask on PrmRoutingTask.RtaId = a.TaskID
where LogTableName like '%Routing%'
and LogValue like '%RtaAniId=397%'
order by 5 desc

Related

Simple SQL Express Full Join Query does not return nulls when it should

Here is the query:
SELECT
AttributeName.ID, Attributes.LinkAnalyses, Attributes.Value, AttributeName.Name
FROM
AttributeName
FULL OUTER JOIN
Attributes ON AttributeName.ID = Attributes.LinkName
I should be getting nulls returned because LinkAnalyses = 88 only has linknames up to 10 where attributename has linknames up to 21. I should get 11 nulls but I get none
Output:
Attributes table:
AttributeName table:
Full join will work based on joining key you are used in your query.
In your query, you use AttributeName.ID = Attributes.LinkName, So if any ID from AttributeName is missing in LinkName column in table Attributes (and vice versa) will return null row.
There have no relation in your column Attributes.LinkAnalysis.
If you want LinkAnalysis wise full join , you can use below query
select
Id,Attributes.LinkAnalyses,Value,Name
from
( SELECT
an.LinkAnalyses,AttributeName.ID,AttributeName.Name
FROM
(Select distinct LinkAnalyses from Attributes ) an
, AttributeName
) A
full join Attributes on Attributes.LinkAnalyses=A.LinkAnalyses and A.ID =Attributes.LinkName

SQL Query – records within the SQL Select statement, but NOT in the table being queried

I have a large list of CustIDs that I need to query on to find if they are within the CUSTOMER table; I want the result to tell me which CustIDs ARE on the table and which CustIDs are NOT on the table.
I provided a short list below to give an idea of what I need to do.
Oracle database
Table: Customer
Primary Key: CustID
Scenario:
Customer table only has the following (2) CustID: ‘12345’, ‘56789’
Sql:
Select * from CUSTOMERS where CUSTID in (‘12345’, ‘56789’, ‘01234’);
I want the result to tell me that both ‘12345’ and ‘56789’ are in the table, AND that ‘01234’ is NOT.
select
v.CustID,
exists (select * from Customer where Customer.CustID = v.CustID)
from (values (12345), (56789), (01234)) v (CustID);
Results:
custid exists
12345 true
56789 true
1234 false
You need a left join or subquery for this. The precise syntax varies by database. Typical syntax is:
select i.custid,
(case when c.custid is not null then 1 else 0 end) as exists_flag
from (select '12345' as custid union all
select '56789' union all
select '01234'
) ci left join
customers c
on c.cust = i.custid;

SELECT Statement in CASE

Please don't downgrade this as it is bit complex for me to explain. I'm working on data migration so some of the structures look weird because it was designed by someone like that.
For ex, I have a table Person with PersonID and PersonName as columns. I have duplicates in the table.
I have Details table where I have PersonName stored in a column. This PersonName may or may not exist in the Person table. I need to retrieve PersonID from the matching records otherwise put some hardcode value in PersonID.
I can't write below query because PersonName is duplicated in Person Table, this join doubles the rows if there is a matching record due to join.
SELECT d.Fields, PersonID
FROM Details d
JOIN Person p ON d.PersonName = p.PersonName
The below query works but I don't know how to replace "NULL" with some value I want in place of NULL
SELECT d.Fields, (SELECT TOP 1 PersonID FROM Person where PersonName = d.PersonName )
FROM Details d
So, there are some PersonNames in the Details table which are not existent in Person table. How do I write CASE WHEN in this case?
I tried below but it didn't work
SELECT d.Fields,
CASE WHEN (SELECT TOP 1 PersonID
FROM Person
WHERE PersonName = d.PersonName) = null
THEN 123
ELSE (SELECT TOP 1 PersonID
FROM Person
WHERE PersonName = d.PersonName) END Name
FROM Details d
This query is still showing the same output as 2nd query. Please advise me on this. Let me know, if I'm unclear anywhere. Thanks
well.. I figured I can put ISNULL on top of SELECT to make it work.
SELECT d.Fields,
ISNULL(SELECT TOP 1 p.PersonID
FROM Person p where p.PersonName = d.PersonName, 124) id
FROM Details d
A simple left outer join to pull back all persons with an optional match on the details table should work with a case statement to get your desired result.
SELECT
*
FROM
(
SELECT
Instance=ROW_NUMBER() OVER (PARTITION BY PersonName),
PersonID=CASE WHEN d.PersonName IS NULL THEN 'XXXX' ELSE p.PersonID END,
d.Fields
FROM
Person p
LEFT OUTER JOIN Details d on d.PersonName=p.PersonName
)AS X
WHERE
Instance=1
Ooh goody, a chance to use two LEFT JOINs. The first will list the IDs where they exist, and insert a default otherwise; the second will eliminate the duplicates.
SELECT d.Fields, ISNULL(p1.PersonID, 123)
FROM Details d
LEFT JOIN Person p1 ON d.PersonName = p1.PersonName
LEFT JOIN Person p2 ON p2.PersonName = p1.PersonName
AND p2.PersonID < p1.PersonID
WHERE p2.PersonID IS NULL
You could use common table expressions to build up the missing datasets, i.e. your complete Person table, then join that to your Detail table as follows;
declare #n int;
-- set your default PersonID here;
set #n = 123;
-- Make sure previous SQL statement is terminated with semilcolon for with clause to parse successfully.
-- First build our unique list of names from table Detail.
with cteUniqueDetailPerson
(
[PersonName]
)
as
(
select distinct [PersonName]
from [Details]
)
-- Second get unique Person entries and record the most recent PersonID value as the active Person.
, cteUniquePersonPerson
(
[PersonID]
, [PersonName]
)
as
(
select
max([PersonID]) -- if you wanted the original Person record instead of the last, change this to min.
, [PersonName]
from [Person]
group by [PersonName]
)
-- Third join unique datasets to get the PersonID when there is a match, otherwise use our default id #n.
-- NB, this would also include records when a Person exists with no Detail rows (they are filtered out with the final inner join)
, cteSudoPerson
(
[PersonID]
, [PersonName]
)
as
(
select
coalesce(upp.[PersonID],#n) as [PersonID]
coalesce(upp.[PersonName],udp.[PersonName]) as [PersonName]
from cteUniquePersonPerson upp
full outer join cteUniqueDetailPerson udp
on udp.[PersonName] = p.[PersonName]
)
-- Fourth, join detail to the sudo person table that includes either the original ID or our default ID.
select
d.[Fields]
, sp.[PersonID]
from [Details] d
inner join cteSudoPerson sp
on sp.[PersonName] = d.[PersonName];

How to create an sql command that has SELECT statements from 2 different tables?

How to create an sql command that has SELECT statements from 2 different tables? For example,
select ID from EMP_details, select job_id from Jobs_details
So how can i possibly merge both into one
Selecting from two or more tables When rows in them tables has some sort of relation so you want to extract the corresponding row you would use a JOIN something like this ....
JOIN
SELECT EMP.ID, JD.job_id
FROM EMP_details EMP INNER JOIN jobs_details JD
ON EMP.CommonColumn = JD.CommonColumn
Results From Two SELECTS
When you have two SELECT statements and just want to get the results returned from them queries into one row you can do something like this ...
SELECT X.A , Y.B
FROM (select ID AS A from EMP_details) X, (select job_id AS B from Jobs_details) Y
This is known as a JOIN in SQL. Your query might look like this:
SELECT EMP_details.ID,
EMP_details.Name,
Job_details.RefNumber
FROM EMP_details,
Jobs_details
WHERE EMP_details.ID = Jobs_details.job_id;
Having a column in both tables by which you can match the rows from the first table to the second one, like for example the job_id in Jobs_details matches job_id in Emp_details, you could do:
SELECT e.ID,j.job_id
FROM EMP_details e
INNER JOIN jobs_details j ON e.job_id = j.job_id
For more information on JOIN's see the documentation.
Have you try
SELECT id FROM (SELECT id FROM EMP_details UNION ALL SELECT id FROM Jobs_details) as temp_table;
Thanks,

How to use a join table when query also contains geography data, in a multi-id query?

Places Table
PlaceId PK
Name
GeoPoint (GeoPoint type)
etc...
PlaceCats Table (the join table)
PlaceId PK FK
CatId PK FK
PlaceCategories Table
CatId PK
Name
etc...
Here's my query, to return places, with entries in the PlaceCats table (by a series of catIds), and within 25km of a Lat/Lng value.
SELECT Places.*
FROM Places
INNER JOIN PlaceCats
ON Places.PlaceId = PlaceCats.PlaceId
WHERE PlaceCats.CatId IN (2,3,4,5)
AND Places.GeoPoint.STDistance(geography::Point(35.75094975999387, 139.39780220389366, 4326)) < ((25 * 1000))
ORDER BY Places.Name ASC
It's returning places, but I need to add DISTINCT after the SELECT... apparently you can't use DISTINCT when selecting geography data. I need to make sure I'm not getting the same place multiple times (as they can have multiple entries in the join table).
Update
When I insert a place into the Places table, the GeoPoint is set like so:
SqlGeography.Point(sentPlace.Lat.Value, sentPlace.Lng.Value, 4326);
It look to me like you have your long/lats the wrong way round.
As for selecting DISTINCT geographies, you can perform the DISTINCT operation over the WKT (Well Known Text) in a nested query, see below:
SELECT
GEOGRAPHY::STGeomFromText(WKT, [PROJECTION]) AS GEOG
FROM
(
SELECT DISTINCT
GEOG.STAsText() AS WKT
FROM
[TABLE_NAME]
) a
Your query would look something like this:
SELECT
a.*
, GEOGRAPHY::STGeomFromText(WKT, 4326) AS GEOG
FROM
(
SELECT DISTINCT
Places.[COL1]
, Places.[COL2]
, Places.[COL3]
, Places.[COL4]
...
...
, Places.GeoPoint.STAsText() AS WKT
FROM
Places
INNER JOIN
PlaceCats
ON
Places.PlaceId = PlaceCats.PlaceId
WHERE PlaceCats.CatId IN (2,3,4,5)
AND
Places.GeoPoint.STDistance(GEOGRAPHY::Point(35.75094975999387, 139.39780220389366, 4326)) < ((25 * 1000))
ORDER BY Places.Name ASC
)a
One further tip, assuming you have a spatial index on your table, it speeds spatial queries up no end by using an index hit:
SELECT *
FROM
[TABLE_NAME] WITH(INDEX([INDEX_NAME]))
WHERE
GEOG.STIntersects.(GEOGRAPHY::Point([Longitude], [Latitude], 4326)) = 1