SQL - Select only statement: How do create something similar to a "Vlookup"? - sql

I am new to stackoverflow so hope I am phrasing this clear enough.
I have a lot of data on our sql server and can only use a Select statement to extract data. I am looking now to extract a certain part out of a part name so I can see how many of that type we use:
SELECT CASE
WHEN Part.Part_No like '%B-123%' THEN 'B-123'
WHEN Part.Part_No like '%B-456%' THEN 'B-456'
WHEN Part.Part_No like '%IW-10%' THEN 'IW-10'
WHEN Part.Part_No like '%T-TLT%' THEN 'T-TLT'
WHEN Part.Part_No like '%B-TLT3060%' THEN 'B-TLT3060'
ELSE NULL END AS Type
FROM dbo.CATEGORY
So rather then writing hundreds of these lines, I was wondering if I can add these in a table and then run through the table like a VLookup. But I can only do it in the select statement without creating new tables ( I am not too sure how this would work with a temp table).
Anyone any ideas?

You could use a CTE for managing your lookup table. You can then join (left join) your table and the lookup table, using LIKE as a join clause.
This query should do it:
WITH cte AS (SELECT '%B-123%' AS a, 'B-123' AS b
UNION SELECT '%B-456%', 'B-456'
UNION SELECT '%IW-10%', 'IW-10'
UNION SELECT '%T-TLT%', 'T-TLT'
UNION SELECT '%B-TLT3060%', 'B-TLT3060')
SELECT c.b
FROM dbo.CATEGORY t
LEFT OUTER JOIN cte c
ON Part.Part_No LIKE c.a
Depending on your data and table structure, it could happen that it gets more than one result for each row (in case one part_no matches more than one case). If that's your case, you could limit it using a GROUP BY on the primary key of the table.

Related

SQL - How to run when you have nested select and output returns multiple rows

I have code like below as I am working on some complex conditions.
select *, (select * from table b where conditions are met)
from table a
The code meets my needs but the problem is that it fails if (select * from table b where conditions are met) returns more than 1 row. Is there a way to work around that? Is there a way to duplicate rows from table a if the second select clause is going to return more than 1 row?
I tried running (select * from table b where conditions are met) part first and then doing left join with table b but that takes way longer time and I would like to avoid if possible
One way to solve the issue would be to serialize tableb to a JSON object using FOR JSON. Something like this
select *, (select * from table b where conditions are met FOR JSON PATH) json_name
from table a
When assigning JSON to a variable or storing in SQL Server it should always be NVARCHAR(MAX) data type. Also, it's always necessary to give columns an explicit name in order to serialize correctly and without causing an error. So it would make sense to expand the wildcard in the SELECT statement, if that's an issue.
Try running this as a left join:
select *, b.*
from table a left join
b
on . . . and <conditions>
Or using outer apply:
select *, b.*
from table a outer apply
(select * from table b where conditions are met) b;

Execute SQL query based on results of a condition

My SQL knowledge is somewhat limited. I have 2 Select statements that returns separate sets of results. Since the tables being queried are different sets of tables for each Select statement I would like to know if it is possible to write it such that it picks which query to execute based on the result returned from a Select Statement on a completely different table, for example:
Select C.ManBtchNum from Table C
If OITM.ManBtchNum = 'Y' then
Select * from Table A
else
Select * from Table B
Apologies for using psuedocode but its the shortest way I can explain this.
I'm not sure if a Case expression can be used here. Any advice would be helpful. Thanks
I have tried both a Case as well as a Union but I'm not getting the results needed. Granted I might be doing something wrong considering my limited knowledge
As an example,
select t1.Val, t2.Val, t3.Val,
case
when(t1.Val = Something)Then (T2.Val)Else(t3.Val)
END
from tablex t1
inner join tabley t2 on t1.commonfield = t2.commonfield
inner join tablez t3 ON t1.commonfield = t3.commonfield

Using ON clause to JOIN tables with same column name

I wanted to ask about the condition of an ON clause while joining tables:
SELECT c_User.ID
FROM c_User
WHERE EXISTS (
SELECT *
FROM c_Group
JOIN c_Member ON (c_Group.Group_Name LIKE 'mcp%')
WHERE
c_Group.Name = c_Member.Parent_Name
AND c_Member.Child_Name = c_User.Lower_User_Name
)
I know that tables c_Member and c_Group have one column with the same name, Directory_ID. What I expected was c_Member and c_Group to join on that column using something like:
c_Group JOIN c_Member ON (c_Group.Directory_ID = c_Member.Directory_ID)
WHERE c_Group.Group_Name like 'mcp%'
How is this condition able to match the rows?
c_Member ON (c_Group.Group_Name LIKE 'mcp%')
Is this is a shorter way of referring to two tables joining on a column with the same name, while applying the LIKE condition?
If so, then can such a style work for a table with multiple column names that are the same?
This is your correlated subquery:
SELECT *
FROM c_Group
JOIN c_Member ON (c_Group.Group_Name LIKE 'mcp%')
WHERE
c_Group.Name = c_Member.Parent_Name
AND c_Member.Child_Name = c_User.Lower_User_Name
This subquery works, but the way it is spelled makes it quite unclear:
The join condition (c_Group.Group_Name LIKE 'mcp%') is not actually not related to the table being joined (c_Member) ; what it actually does is apply filter on table c_Group that makes it filter on (there is no magic such as shorter way of referring to two tables joining on a column with the same name, while applying the LIKE condition). It would make more sense to move it to the WHERE clause (this would still be functionaly equivalent).
On the other hand, the WHERE clause contains conditions that relate to the tables being joined (for example: c_Group.Name = c_Member.Parent_Name). A more sensible option would be to put them in the ON clause of the JOIN.
Other remarks:
when using NOT EXISTS, you usually would prefer SELECT 1 instead of SELECT *, (most RDBMS will optimize this under the hood for you, but this makes the intent clearer).
table aliases can be used to make the query more readable
I would suggest the following syntax for the query (which is basically syntaxically equivalent to the original, but a lot clearer):
SELECT u.ID
FROM c_User u
WHERE EXISTS (
SELECT 1
FROM c_Group g
JOIN c_Member m ON g.Name = m.Parent_Name AND m.Child_Name = u.Lower_User_Name
WHERE g.Group_Name LIKE 'mcp%'
)

Join in Google BigQuery via Cloud Datalab

I am trying to do JOIN on two columns from two different tables (one of them is a view) in Google BigQuery. I have tried this numerous ways, but have received this error the most consistently:
invalidQuery: 2.1 - 0.0: JOIN cannot be applied directly to a table union or to a table wildcard function. Consider wrapping the table union or table wildcard function in a subquery (e.g., SELECT *).
Here is my SQL (legacy) query:
SELECT
blp_today.beta_key,
blp_today.px_last,
blp_today.eqy_weighted_avg_px,
blp_today.created_date,
blp_today.security_ticker,
ciq_company_stg.ticker,
ciq_company_stg.ciq
FROM
[fcm-dw:acquisition_bloomberg.blp_today],
[fcm-dw:acquisition_ciq]
JOIN
blp_today.security_ticker AS ticker
ON
blp_today.security_ticker = ciq_company_stg.ticker
LIMIT 1000
Any help would be much appreciated.
I think you either want something like this:
SELECT * FROM(SELECT
beta_key,
px_last,
eqy_weighted_avg_px,
created_date,
security_ticker,
FROM
[fcm-dw:acquisition_bloomberg.blp_today],
[fcm-dw:acquisition_ciq] ) as a
JOIN
blp_today.security_ticker AS ticker
ON
a.security_ticker = ciq_company_stg.ticker
LIMIT 1000
//edit: I kind of missed earlier that the table that you are joining (after your join statement) does not actually seem to be a table. Are you trying to join or to union these two tables: [fcm-dw:acquisition_bloomberg.blp_today] and [fcm-dw:acquisition_ciq] ? And is the latter even a table? Your code seems to indicate that there is another table named: [fcm-dw:acquisition_ciq.ciq_company_stg]?
First wrap your union into a sub select then join the result
select ...
FROM
(select * from
[fcm-dw:acquisition_bloomberg.blp_today],
[fcm-dw:acquisition_ciq] ) t
JOIN
blp_today.security_ticker AS ticker

Create table that is table 1 minus table 2 based on three criteria

I have a table of LoggedDischarges and another table of ActualDischarges.
I am trying to generate a query that will give me all the fields from ActualDischarges excluding those already in LoggedDischarges based on AgencyID, Program and ActivityEndDate
A client can be in multiple programs and be discharged from multiple on the same day. I need to make sure I get LoggedDischarges from each program.
This is what I have but am not sure how to add the other criteria.
select * from ActualDischarges
where (agencychildid ) not in
(select agencyid from LoggedDischarges)
Thank you,
Steve Hathaway
Even if your DBMS supports multiple columns in a subquery like
where (AgencyID, Program, ActivityEndDate) not in
( select AgencyID, Program, ActivityEndDate
from ... )
you better switch to a NOT EXISTS (in case of any NULLs):
select * from ActualDischarges as aD
where NOT EXISTS
(select * from LoggedDischarges as lD
where aD.AgencyID = lD.AgencyID
and aD.Program = lD. Program
and aD.ActivityEndDate= lD.ActivityEndDate)
For this type of match, I would recommend a LEFT JOIN with an IS NULL at the end to determine that the second table does not have the record:
SELECT a.*
FROM ActualDischarges AS a
LEFT JOIN LoggedDischarges AS l
ON agencyid=agencychildid
AND a.program=l.program
AND a.ActivityEndDate=l.ActivityEndDate
WHERE l.agencyid IS NULL
As a side note, definitely avoid using multiple IN statements for situations like this WHERE NOT IN (...) AND NOT IN (...) etc. as you end up excluding records which match different records in LoggedDischarges for different reasons, which is rarely the desired result.