SQL Join two tables with different number of rows get all rows from one table - sql

I'm trying to join two tables with a different number of rows. Client Number is an identifying field in both tables.
The first table includes the client number for all clients.
so either could be referenced). To complicate things further, the ClientNumber2 field is a text field but I need it to be a number like the other client number fields. There is also a region field in the second table that I need to limit to certain region numbers.
The second table includes the client number only for clients who meet certain specifications. Some of the clients in the second table have a second client number.
I want to create a new column that shows the client number from the first table for all clients who do not exist in the second table, shows the second client number in the second table if it exists, otherwise, the client number from the first table (which is the same as client number in the first column of the second table
I've included the syntax I'm using below. It runs without errors. The OriginalCN field returns the desired value for those with a value in ClientNumber2 of Table 2 but is returning null values for all others. I cannot figure out how to get it to work correctly. I've also included sample tables and my desired table. Any help is greatly appreciated!
CLIENT TABLE 1
CLIENT NUMBER
1
2
3
4
5
6
7
8
CLIENT TABLE 2
CLIENT NUMBER 2ND CLIENT NUMBER REGION
2 14 1
6 2
8 15 2
DESIRED RESULT
1
14
3
4
5
6
7
15
Here is the syntax I am using:
SELECT
TABLE2.CLIENTNUMBER
TABLE1.CLIENTNUMBER
CASE
WHEN TABLE2.CLIENTNUMBER IS NULL THEN TABLE1.CLIENTNUMBER
WHEN TABLE2.CLIENTNUMBER2 IS NULL THEN TABLE2.CLIENTNUMBER
WHEN TABLE2.CLIENTNUMBER2 = ' ' THEN TABLE2.CLIENTNUMBER
ELSE
CAST(TABLE2.CLIENTNUMBER2 AS INT)
END AS OriginalCN
FROM DSS.DBO.TABLE1
LEFT OUTER JOIN
RPTO.DBO.TABLE2
ON
DSS.DBO.TABLE1.CLIENTNUMBER = RPTO.DBO.TABLE2.CLIENTNUMBER
WHERE TABLE2.REGION IN (1,2,3)

Try this:
SELECT COALESCE(CAST(NULLIF(t2.ClientNumber2,' ') As Int), t1.ClientNumber) As ClientNumber
FROM DSS.DBO.TABLE1 t1
LEFT JOIN RPTO.DBO.TABLE2 t2 ON t1.CLIENTNUMBER = t2.CLIENTNUMBER
WHERE COALESCE(t2.REGION, 1) IN (1,2,3)

Try this..
CREATE TABLE #CLIENT_TABLE_1
(CLIENTNUMBER INT)
INSERT #CLIENT_TABLE_1
VALUES (1),(2),(3),(4),(5),(6),(7),(8)
CREATE TABLE #CLIENT_TABLE_2
(CLIENTNUMBER INT,scNDCLIENTNUMBER varchar(10),REGION INT)
INSERT #CLIENT_TABLE_2
VALUES( 2,'14',1),(6,' ',2),(8,'15',2)
SELECT CASE
WHEN b.CLIENTNUMBER IS NOT NULL
AND len(b.scNDCLIENTNUMBER)>0 THEN b.scNDCLIENTNUMBER
ELSE a.CLIENTNUMBER
END Result
FROM #CLIENT_TABLE_1 a
LEFT JOIN #CLIENT_TABLE_2 b
ON a.CLIENTNUMBER = b.CLIENTNUMBER
Output :
+------+
|Result|
+------+
| 1 |
| 14 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 15 |
+------+

Related

How to get previous row value in present row in sql server

Is there a way we can get previous row data in present row in SQL Server
For eg I have a table as
id | name
1 | abc
2 | def
3 | xyz
I need to query data in the following manner .. so as to concatenate previous row with present one
This way
id | name
1 | abc
2 | abcdef
3 | abcdefxyz
I tries with lag() but, couldn't figure out what am I doing wrong. I am very new in SQL Server.. I am not aware of other functions that could help
Thanks in advance
you can use String_agg function like below
create table t (id int, name nvarchar(max));
insert into t values (1 , 'abc'),(2, 'def'),(3,'xyz');
select t1.id,string_agg(t2.name,'') from t t1 left join t t2
on t1.id>=t2.id
group by t1.id
demo link

Suggestion for sql scenario

I am having two columns in table
InventoryId | RevisionId
-------------------------
1 | 1
2 | 1
2 | 2
2 | 2
3 | 1
3 | 2
3 | 3
3 | 3
but from now on I want to prevent following records
2 | 2
2 | 2
3 | 3
3 | 3
So I thought to create a unique index on these two columns
but the table having so much existing data. So anything we can do this situation.
Any suggestion?
you can use a trigger to prevent new rows being added with duplicate values
look at this example
create trigger TR_UI_YourTable on YourTable
for update, insert as
begin
set nocount on
if exists (select 1 from inserted i where i.InventoryId = i.RevisionId)
begin
;throw 99001, 'no dupes allowed anymore...', 1
end
end
A better solution would be to move the duplicates to a seperate table for history, and then add a check constraint on these 2 columns
EDIT
you could do it by an check constraint like this
alter table yourtable
add constraint chk_dupes
check ((InventoryId <> RevisionId) or (id <= 12345))
where 12345 is the highest value of the column id now.
You will have to test it a bit if it works on all situations.
Also, it will only work if all new rows have a value in id that is larger then the current highest value (12345 in my example)

Ntile function not dividing groups evenly when being ran from stored procedure

I have the following code inside a stored procedure.
select
ID,NTILE(2) OVER (Partition by GroupID order by newID()) as RandomSplit
into #TempSplit
from TableA
where IsUpdated = 1
Update a
set a.SplitColumn = CASE WHEN b.RandomSplit = 1 THEN 'A'
WHEN b.RandomSplit = 2 THEN 'B'
END
from Table A a
inner join #TempSplit b
on a.ID = b.ID and a.IsUpdated = 1
This code works as expected and produces the data table below.
GroupID SplitColumn
1 | A
1 | A
1 | B
1 | B
2 | A
3 | A
3 | B
However,when I execute this code from the stored procedure I get the following results
GroupID SplitColumn
1 | A
1 | A
1 | A
1 | B
2 | A
3 | A
3 | B
This is sample data but basically what is happening is that when I execute from the stored procedure the groups are not distributed evenly(in the real data the variation is by thousands rather than just one). Not sure what is exactly causing this behavior since again if I execute the code manually it comes up with the correct behavior.
Also I know this is a small sample of what is happening, but its also not happening for all GroupIDs. Meaning GroupID = 3 always gets split correctly into two even groups, while say GroupID = 1 always gets wrongly split.
You are creating #TempSplit only for the rows where IsUpdated = 1.
However, you are joining back to all the values. If id is duplicated in TableA, then you would get results as you see.

TSQL change in query to and query

I have one to many relationship table
ReviewId EffectId
1 | 2
1 | 5
1 | 8
2 | 2
2 | 5
2 | 9
2 | 3
3 | 3
3 | 2
3 | 9
In the site the users select each effect he chooses, and I get all the relevant review.
I make an in query
For example if the user select effects 2 and 5
My query: “
select reviewed from table_name where effected in(2,5)
Now I need get all the review that contain both effect
All reviews that has effect 2 and effect 5
What is the best query to make this?
Important for me that the query will run as quick as possible.
And for this I can also change the table schema (if needed ) like add a cached field that contain all the effect with comma like
Reviewed cachedEffects
1 | ,2,5,8
2 | ,2,5,9,3,
3 | ,3,2,9
You can do it this way:
select reviewid
from
tbl
where effectid in (2,5)
group by reviewid
having count(distinct effectid) > 1
Demo
count (distinct effectid) is used to ensure that the results contain only those reviewIDs which have multiple records with different values of effectID. The where clause is used to filter out based on your filter condition of having both 2 and 5.
The key thing to note here is that we are grouping by reviewID, and also using the count of distinct effectID values to ensure that only those records which have both 2 and 5 are returned. If we did not do so, the query would return all rows which have effectID equal to either 2 or 5.
For improving performance, you could create an index on reviewID.

Transforming a 2 column SQL table into 3 columns, column 3 lagged on 2

Here's my problem: I want to write a query (that goes into a larger query) that takes a table like this;
ID | DATE
A | 1
A | 2
A | 3
B | 1
B | 2
and so on, and transforms it into;
ID | DATE1 | DATE2
A | 1 | 2
A | 2 | 3
A | 3 | NOW
B | 1 | 2
B | 2 | NOW
Where the numbers are dates, and NOW() is always appended to the most recent date. Given free rein I would do this in Python, but unfortunately this goes into a larger query. We're using SyBase's SQL Anywhere 12, I think? I interact with the database using SQuirreL SQL.
I'm very stumped. I thought (SQL query to transform a list of numbers into 2 columns) would help, but I'm afraid I don't know enough to make it work. I was thinking of JOINing the table to itself, but I don't know how to SELECT for only the A-1-2 rows instead of the A-1-3 rows as well, for instance, or how to insert the NOW() value into it. Does anyone have any ideas?
I made a an sqlfiddle.com to outline a solution for your example. You were mentioning dates, but using integers so I chose to do an integer example, but it can be modified. I wrote it in postgresql so the coalesce() function can be substituted with nvl() or similar. Also, the parameter '0' can be substituted with any value, including now(), but you must change the data type of the "i" column in the table to be a date as well. Please let me know if you need further help on this.
select a.id, a.i, coalesce(min(b.i),'0') from
test a
left join test b on b.id=a.id and a.i<b.i
group by a.id,a.i
order by a.id, a.i
http://sqlfiddle.com/#!15/f1fba/6