Dynamic SQL Case statement? - sql

I have a table that is called DefaultCountries.
It contains the following columns:
CountryID INT
DefaultCountryID INT
CountryRank INT
I have 29 different countries with varying data for each country. For example:
CountryID of 1 has 2 records:
CountryID of 7 has 3 records
I have a table variable #CountryData that I'm trying to join to that currently has data for CountryIDs 1 and 10.
I would like to be able to match up to the DefaultCountryID found in the DefaultCountries table. So if I pass in CountryID = 1, I could do something like:
SELECT TOP 1 DefaultCountryID
WHERE CountryID = 1 -- that is my simple case.
Where I'm having an issue is where there are more than 2+ rows. As in my example for CountryID = 7. Basically I want to have something where if there is no records in my table that I'm trying to join to with the 1st record (CountryRank = 1) then I would like it to search for the next record.
So searching for CountryID = 7, then if nothing, then CountryID = 10 (so on and so forth).
I've tried different variations of this LEFT JOIN
SELECT *
FROM #CountryData cd
LEFT JOIN DefaultCountries dc ON dc.defaultCountryid = cd.CountryID
AND cd.CountryID = 7
But this just brings back all the data (1 & 10). Do I have to use a loop to do this the way I'm describing? I thought about a CASE statement as well, but since I could have more than 2+ in the DefaultCountries table I'm not sure how I could keep searching.
I tried doing an IN statement, but I have 2 issues there. I can't do an order by in the IN statement as I get the following message:
The ORDER BY clause is invalid in views, inline functions, derived
tables, subqueries, and common table expressions, unless TOP, OFFSET
or FOR XML is also specified.
And even if there is a way to make sure I'm searching in the order I want using an IN statement, I want to make sure it stops searching on the 1st one it finds. So to expand on my example, if table (#CountryData) table now contains records where CountryID = 7 and CountryID = 10 I only want to return the records where CountryID = 7.

If i'm following you right you can just use a CTE
with cte as(
select
CountryID,
DefaulteCountryID,
ROW_NUMBER() over (partition by CountryID order by CountryRank) as rn
from DefaultCountries
where DefaultCountryID in (select distinct CountryID from #CountryData))
Then just join to this cte where rn = 1
So this would satisfy "Basically I want to have something where if there is no records in my table that I'm trying to join to with the 1st record (CountryRank = 1) then I would like it to search for the next record" meaning if there wasn't a 1 you'd get 2, or 3, or what ever the next order number is.

Related

SQL: Joining two table based on certain description

I have two tables:
And I want to add GTIN from table 2 to table 1 based on brand name. Though I cant use = or like because as you see in highlighted row they are not fully matched.
For example
Second row in table 1, suppose to have first GTIN from table 2 because both are Ziagen 300mg tablet. However all of what I tried failed to match all row correctly.
Postgres has a pg_trgm module described here. Start with a cross join joining both tables and calculate the similarity(t1.brand,t2.brand) function, which returns the real number.
Next filter the results based on some heuristic number. Then narrow down with choosing single best match using row_number() window function.
The results might be not accurate, you could improve it by taking generic similarity into account as well.
with cross_similarity(generic1,brand1,gtin,brand2,generic2,sim) as (
select *, similarity(t1.brand, t2.brand) as sim
from t1,
t2
where similarity(t1.brand, t2.brand) > 0
)
, max_similarity as (
select *,
row_number() over (partition by gtin order by sim desc) as best_match_rank
from cross_similarity
)
select * from max_similarity where best_match_rank =1;

Find table with only two rows. Access 2016

I'm looking for a query that I can use in MS Access 2016 which will give me all Company ID's that have the values "Iphone" and "Ipad". So all CompanyID that has only two rows with specific values.
CompanyID Product_Name
1 Iphone
1 Ipad
1 Headphones
2 Iphone
2 Galaxy
3 Playstation 4
3 Nintendo Switch
4 Iphone
4 Ipad
In the example table above I will therefore get the CompanyID = 4.
I have tried to use the same logic as in SQL from the this post but Access doesn't allow syntax USING.
The SQL query used in post is:
SELECT CompanyID
FROM DATA AS a
JOIN DATA AS b
USING (CompanyID)
WHERE a.Product_Name = "Iphone"
AND b.Product_Name = "Ipad";
Any feedback is much appreciated.
Since you state:
So all CompanyID that has only two rows with specific values... In the
example table above I will therefore get the CompanyID = 4.
It would seem that you require the CompanyID for which the only two Product_Name values are Ipad & Iphone, with no other values associated with the CompanyID.
To obtain this result, I might suggest the following SQL query:
select t.companyid
from data t
group by t.companyid
having max(t.product_name in ('Iphone','Ipad'))=-1
Which will return:
CompanyID
4
Here, for every record within each group of records associated with a given CompanyID, the expression t.product_name in ('Iphone','Ipad') is evaluated.
This expression will either return True (-1) or False (0).
If all records within the group are either 'Iphone' or 'Ipad', then this expression will return True (-1) for every record, and the maximum over the group will be -1.
Whereas, if any record within the group is some other value, this expression will return False (0) and therefore the maximum of the group will be 0, thus excluding it from the result.
You can use an INNER JOIN to filter the results that do not contain both values:
SELECT a.CompanyID
FROM (
SELECT CompanyID
FROM DATA
WHERE Product_Name = 'IPhone'
) a
INNER JOIN (
SELECT CompanyID
FROM DATA
WHERE Product_Name = 'Ipad'
) b ON b.CompanyID = a.CompanyID
Output:
CompanyID
1
4
How does this work?
Firstly all results that have an IPhone are gathered. Then this is joined with all results that have an IPad. Only results with both rows matching (because of the INNER JOIN) will be returned.
While late to this, it looks like they're only being pulled from one table - DATA. If that's the case then the easiest solution should just be
SELECT DATA.CompanyID
FROM (DATA)
WHERE DATA.Product_Name = "Iphone"
AND DATA.Product_Name = "Ipad";
For Access, the FROM statement is generally only used for combining tables, or queries, and the data manipulation is in the other statements.
If there's more than one table and the connection between the two tables is CompanyID, then it should look more like this;
SELECT DATA1.CompanyID
FROM (DATA1 INNER JOIN DATA1.CompanyID ON DATA2.CompanyID)
WHERE DATA2.Product_Name = "Iphone"
AND DATA2.Product_Name = "Ipad";

SQL-Oracle: Updating table multiple row based on values contained in the same table

I have one table named: ORDERS
this table contains OrderNumber's which belong to the same person and same address lines for that person.
However sometimes the data is inconsistent;
as example looking at the table screenshot: Orders table with bad data to fix -
you all can noticed that orderNumber 1 has a name associated to and addresses line1-2-3-4. sometimes those are all different by some character or even null.
my goal is to update all those 3 lines with one set of data that is already there and set equally all the 3 rows.
to make more clear the result expected should be like this:
enter image description here
i am currently using a MERGE statement to avoid a CURSOR (for loop )
but i am having problems to make it work
here the SQL
MERGE INTO ORDERS O USING
(SELECT
INNER.ORDERNUMBER,
INNER.NAME,
INNER.LINE1,
INNER.LINE2,
INNER.LINE3,
INNER.LINE4
FROM ORDERS INNER
) TEMP
ON( O.ORDERNUMBER = TEMP.ORDERNUMBER )
WHEN MATCHED THEN
UPDATE
SET
O.NAME = TEMP.NAME,
O.LINE1 = TEMP.LINE1,
O.LINE2 = TEMP.LINE2,
O.LINE3 = TEMP.LINE3,
O.LINE4 = TEMP.LINE4;
the biggest issues i am facing is to pick a single row out of the 3 randomly - it does not matter whihc of the data - row i pick to update the line/s
as long i make the records exaclty the same for an order number.
i also used ROWNUM =1 but it in multip[le updates will only output one row and update maybe thousand of lines with the same address and name whihch belong to an order number.
order number is the join column to use ...
kind regards
A simple correlated subquery in an update statement should work:
update orders t1
set (t1.name, t1.line1, t1.line2, t1.line3, t1.line4) =
(select t2.name, t2.line1, t2.line2, t2.line3, t2.line4
from orders t2
where t2.OrderNumber = t1.OrderNumber
and rownum < 2)

How to compare records and update one column

It is a little bit tricky for me so I need your help :)
I want to update the column Relevant to 0 WHERE Contract_Status_Code is 10 OR the Date_Contract_start YEAR is the same AND the Ranking_Value is lower than the other one ON all records that have the same VIN.
So I want to compare all records which have the same VIN.
Few examples to illustrate it:
I have there two records with the VIN = 123456. One of them (ID = 6847) has a higher Ranking_Value (7) than the other one (3). The YEAR is the same as well so I want to update the column relevant to 0 where the ID is 8105.
Two records with the VIN = 654321. Both of them have the same Ranking_Value but the record with the id = 11012 has the value 10 for the column Contract_Status_Code so I want to update the relevant column to 0 where the ID = 11012.
The last two records... They have the VIN = 171819. The first one (ID = 11578) has the higher Ranking_Value. But they have a different year where the contract has started. So I don't want to update both.
It is also possible that there are three or four records with the same VIN.
I hope you understand my problem. I'm from Germany so sorry for my English :)
By considering your ID column as unique or Identity column, I can suggest you the below query for your solution:
With cte
As
(Select a.Id, a.VIN From Table a
Join (Select max(Ranking_Value) ranks,VIN From Table Group By VIN, Year(Date_Contract_start)) b
on a.VIN=b.VIN And a.Ranking_Value = b.ranks)
update table
set Relevant = 0
where (Contract_Status_Code = 10) Or
ID Not In (Select id from cte)
update table1
set Relevant = 0
where Contract_Status_Code = 10
or (VIN,Year,Ranking_value) not in(
select VIN,Year,max(Ranking_Value)
from table1
group by VIN,Year
)

How to get one common value from Database using UNION

2 records in above image are from Db, in above table Constraint are (SID and LINE_ITEM_ID),
SID and LINE_ITEM_ID both column are used to find a unique record.
My issues :
I am looking for a query it should fetch the recored from DB depending on conditions
if i search for PART_NUMBER = 'PAU43-IMB-P6'
1. it should fetch one record from DB if search for PART_NUMBER = 'PAU43-IMB-P6', no mater to which SID that item belong to if there is only one recored either under SID =1 or SID = 2.
2. it should fetch one record which is under SID = 2 only, from DB on search for PART_NUMBER = 'PAU43-IMB-P6', if there are 2 items one in SID=1 and other in SID=2.
i am looking for a query which will search for a given part_number depending on Both SID 1 and 2, and it should return value under SID =2 and it can return value under SID=1 only if the there are no records under SID=2 (query has to withstand a load of Million record search).
Thank you
Select *
from Table
where SID||LINE_ITEM_ID = (
select Max(SID)||Max(LINE_ITEM_ID)
from table
where PART_NUMBER = 'PAU43-IMB-P6'
);
If I understand correctly, for each considered LINE_ITEM_ID you want to return only the one with the largest value for SID. This is a common requirement and, as with most things in SQL, can be written in many different ways; the best performing will depend on many factors, not least of which is the SQL product you are using.
Here's one possible approach:
SELECT DISTINCT * -- use a column list
FROM YourTable AS T1
INNER JOIN (
SELECT T2.LINE_ITEM_ID,
MAX(T2.SID) AS max_SID
FROM YourTable AS T2
GROUP
BY T2.LINE_ITEM_ID
) AS DT1 (LINE_ITEM_ID, max_SID)
ON T1.LINE_ITEM_ID = DT1.LINE_ITEM_ID
AND T1.SID = DT1.max_SID;
That said, I don't recall seeing one that relies on the UNION relational operator. You could easily rewrite the above using the INTERSECT relational operator but it would be more verbose.
Well in my case it worked something like this:
select LINE_ITEM_ID,SID,price_1,part_number from (
(select LINE_ITEM_ID,SID,price_1,part_number from Table where SID = 2)
UNION
(select LINE_ITEM_ID,SID,price_1,part_number from Table SID = 1 and line_item_id NOT IN (select LINE_ITEM_ID,SID,price_1,part_number from Table SID = 2)))
This query solved my issue..........