maintain distinct results with table join - sql-server

I have a relatively simple query.
SELECT DISTINCT
tA.id AS 'id'
//as pointed out, I could just select tB.value without the case here
,CASE WHEN tB.udf_id IN ('1')
THEN tB.value
END AS 'side'
FROM tableA tA
INNER JOIN tableB tB ON tA.id = tB.id
WHERE tB.udf_id IN ('1')
tableA
|id| date |
|--|----------|
|1 | 1/1/2023 |
|2 | 1/2/2023 |
|3 | 1/3/2023 |
tableB
|id|udf_id| value |
|--|------|---------|
|1 | 1 | right |
|1 | 2 | active |
|2 | 1 | left |
|2 | 2 | NULL |
|3 | 3 | right |
|3 | 3 | pending |
This will give me 1 row per "id" because of the WHERE clause.
Result Output
|id| value |
|--|---------|
|1 | right |
|2 | left |
|3 | right |
However, I now want to add another condition to what data gets returned.
I only want to return results;
tB.value is not NULL when tB.udf_id=2
(pseudocode, I know this doesn't work this way)
So the new result output would look the same but drop id=2 because tb.value=NULLwhen tb.udf_id=2.
New Result Output
|id| value |
|--|---------|
|1 | right |
|3 | right |
I'm struggling on how to do this. Just adding another udf_id value creates multiple rows of results instead of the one, which I don't want. And I don't believe I can express my codition in the WHERE clause like that.
My assumption is that I need to do some sort of subquery?

Below code will check for udf_id = '2' without "joining" an extra set of records
SELECT DISTINCT
tA.id AS 'id'
//as pointed out, I could just select tB.value without the case here
,CASE WHEN tB.udf_id IN ('1')
THEN tB.value
END AS 'side'
FROM tableA tA
INNER JOIN tableB tB ON tA.id = tB.id
WHERE tB.udf_id IN ('1')
-- This will check for non NULL udf_id = '2' value
AND EXISTS( SELECT * FROM tableB AS ID2 WHERE tA.id = ID2.id AND udf_id = '2' AND value IS NOT NULL )

Related

SQL Sub rows - UNION vs JOIN

i would like to join 2 table but not duplicating all data.
try to be more clear
I have table_A
| ID | Description | Total
| 1. | Test a. | 10
| 2. | Test B. | 8
and my total is 18
Table_B
|ID| Site
|1 | Site A
|1 | Site B
|2 | Site C
If i do a left
Select a.ID,a.Description,b.Site,a.Total from table_a as a
left outer join table_b as b on a.id =b.it
i get
| ID | Description | Site | Total
| 1. | Test a. | Site A|. 10
| 1. | Test a. | Site B|. 10
| 2. | Test B. | Site C| 8
so my total became 28
i would like to get something like
| a.ID |b.ID| Description | Site | Total
| 1. | | Test a. | |. 10
| 1. | 1 | | Site A|
| 1. | 1 | | Site B|
| 2. | | Test B. | | 8
| 2. | 2 | | Site C|
so i can have it in excel and create a group by into the row
I think this is what you want. There are a few methods of doing this, one is using a UNION to get the 2 datasets:
SELECT aID,
bID,
description,
Site,
Total
FROM (SELECT a.ID AS aID,
b.ID AS bID,
a.description,
b.Site,
NULL AS Total
FROM dbo.TableA a
JOIN dbo.TableB b ON A.ID = B.ID
UNION ALL
SELECT a.ID AS aID,
NULL,
a.description,
NULL,
a.Total
FROM dbo.TableA a) U
ORDER BY aID,
bID,
Site;
db<>fiddle

Why is my update query not actually updating?

i have been trying out an update query with information from another table but somehow is not working and i can't figure out why it is
this is how i'm doing the query:
UPDATE x
SET x.sheet_expedient=db_data.sheet_expedient
FROM dbo_expedient_reports x
INNER JOIN db_data ON x.sheet_expedient= db_data.sheet_expedient
WHERE x.sheet_expedient IS NULL
why is this not working? thanks in advance.
EDIT
i see some people a little confused about the structure of the table, here it is
dbo_expedient_reports
report_id|sheet_expedient|report_number|report_date|notificacion_date|report_status|
1 | NULL | NULL | NULL | NULL | NULL |
2 | NULL | NULL | NULL | NULL | NULL |
3 | NULL | NULL | NULL | NULL | NULL |
4 | NULL | NULL | NULL | NULL | NULL |
5 | NULL | NULL | NULL | NULL | NULL |
6 | NULL | NULL | NULL | NULL | NULL |
7 | NULL | NULL | NULL | NULL | NULL |
8 | NULL | NULL | NULL | NULL | NULL |
db_data (this one has the information i want to put on dbo_expedient_reports)
sheet_expedient|report_date|name_expedient_owner|address_expedient|
1 | 01-01-2011|mike | his house 123 |
2 | 06-06-2006|josh | their house 456 |
3 | 07-07-2007|andrew | his place 789 |
4 | 08-08-2008|frank | somewhere 1111 |
5 | 09-09-2009|chad | anywhere 2222 |
6 | 10-10-2010|zack | nowhere 3333 |
7 | 11-11-2011|steve | everywhere 4444 |
8 | 12-12-2012|mark | here 5555 |
The main idea is that the sheet expedient information goes to dbo_expedient reports for an instance and the other rows from db_data go another tables where the information will be placed, you may think, the sheet expedient is the same as the id, well that is not the case since the sheet_expedient gets to a limit (around 800) and then starts over again so it's different from the id, while the sheet_expedient will hit the number 800 then will start again so the id will be id 800 sheet_expedient 800 and then id 801 sheet_expedient 1
i hope a clarified some doubts for a better understanding, thanks for all of the replies
Based on your comment, you have JOIN on the wrong column. Here is the fix.
UPDATE x
SET x.sheet_expedient=db_data.sheet_expedient
FROM dbo_expedient_reports x
INNER JOIN db_data ON x.report_id = db_data.sheet_expedient --here is the change
WHERE x.sheet_expedient IS NULL
Note, all this is really going to do is duplicate the report_id column. That is, the report_id column will match the sheet_expedient column for your dbo_expedient_reports table. I'm not sure what the point of this is.
Also, the WHERE clause isn't needed based on this sample data.
I'm not too sure what would you like to achieve.
If x.sheet_expedient is expect to be NULL then why did you use it in the join?
Do you have any other fields that you can use to join the two tables?
Think you need a left join:
UPDATE x
SET x.sheet_expedient=db_data.sheet_expedient
FROM dbo_expedient_reports x
LEFT JOIN db_data ON x.sheet_expedient= db_data.sheet_expedient
WHERE x.sheet_expedient IS NULL
To check try this:
WITH cte AS
(SELECT x.sheet_expedient [FieldToUpdate]
, db_data.sheet_expedient [NewValue]
, *
FROM dbo_expedient_reports x
INNER JOIN db_data ON x.sheet_expedient = db_data.sheet_expedient
WHERE x.sheet_expedient IS NULL)
--UPDATE cte SET [FieldToUpdate] = [NewValue];
SELECT * FROM cte;
I usually wrap my updates into a cte before running them. Allows me to see values before and values after. While this won't answer your question, it should help you identify why.
I've commented out the update statement, once the select is returning the rows and values you expect, uncomment the update, and comment out the select.

Update TableA values based on Values from TableB (multiple options)

I have Two tables:
TableA
+************************************+
|Col1 | code | Country | Value2 |
+************************************+
|Field1 | IN | INDIA | NA |
|Field2 | CA | CANADA | NA |
|Field3 | US | USA | NA |
+************************************+
TableB
+***************************+
|Field1 | Field2 | Field3 |
+***************************+
|1 | 4 | IN |
|2 | 5 | CA |
|3 | 6 | - |
+***************************+
I am trying to update column Field3 in TableB, Based on values from Column Country in TableA
That is: If Field3 in TableB has Value IN then it should get updated to India
or If Filed3 has Value CA it should get updated to Canada
and in the third case if no matching value is present then it should get update to "NA" or "NotSpecified"
So far I have tried updating TableB using a INNER JOIN:
UPDATE TableB SET TableB.Field3 = TableA.Country
FROM TableB INNER JOIN TableA ON TableB.Field3 = TableA.Code
I am really struggling update table based on multiple IF statements? Should I use CASE?
Any help or suggestions would be much appreciated.
Use a LEFT JOIN with an ISNULL.
UPDATE TableB SET
Field3 = ISNULL(TableA.Country, 'NA')
FROM
TableB
LEFT JOIN TableA ON TableB.Field3 = TableA.Code
Using a LEFT JOIN won't force all TableB records to join against a TableA record, and the ISNULL will set a default value in case the Code doesn't exist on TableA.

Exclude Secondary ID Records from Original SELECT

I'm relatively new to SQL and am running into a lot of issues trying to figure this one out. I've tried using a LEFT JOIN, and dabbled in using functions to get this to work but to no avail.
For every UserID, if there is a NULL value, I need to remove all records of the Product ID for that UserID from my SELECT.
I am using SQL Server 2014.
Example Table
+--------------+-------------+---------------+
| UserID | ProductID | DateTermed |
+--------------+-------------+---------------+
| 578 | 2 | 1/7/2017 |
| 578 | 2 | 1/7/2017 |
| 578 | 1 | 1/15/2017 |
| 578 | 1 | NULL |
| 649 | 1 | 1/9/2017 |
| 649 | 2 | 1/11/2017 |
+--------------+-------------+---------------+
Desired Output
+--------------+-------------+---------------+
| UserID | ProductID | DateTermed |
+--------------+-------------+---------------+
| 578 | 2 | 1/7/2017 |
| 578 | 2 | 1/7/2017 |
| 649 | 1 | 1/9/2017 |
| 649 | 2 | 1/11/2017 |
+--------------+-------------+---------------+
Try the following:
SELECT a.userid, a.productid, a.datetermed
FROM yourtable a
LEFT OUTER JOIN (SELECT userid, productid, datetermed FROM yourtable WHERE
datetermed is null) b
on a.userid = b.userid and a.productid = b.productid
WHERE b.userid is not null
This will left outer join all records with a null date to their corresponding UserID and ProductID records. If you only take records that don't have an associated UserID and ProductID in the joined table, you should only be left with records that don't have a null date.
You can use this WHERE condition:
SELECT
UserID,ProducID,DateTermed
FROM
[YourTableName]
WHERE
(CONVERT(VARCHAR,UserId)+
CONVERT(VARCHAR,ProductID) NOT IN (
select CONVERT(VARCHAR,UserId)+ CONVERT(VARCHAR,ProductID)
from
[YourTableName]
where DateTermed is null)
)
When you concatenate the UserId and the ProductId get a unique value for each pair, then you can use them as a "key" to exclude the "pairs" that have the null value in the DateTermed field.
Hope this help.

How to get the count of each distinct value in Multiple columns and get the result in separate columns?

I need the following table to be queried to get the result given below the table.
Table:
----------------------------------
| Name | Age | slot |
|-------|--------|---------------|
|A |20 | 1 |
|B |30 | 2 |
|C |30 | 1 |
|D |20 | 1 |
|E |40 | 2 |
|F |40 | 3 |
|G |50 | 3 |
----------------------------------
Result:
-------------------------------------------
|Age |Age_Count |Slot |Slot_Count|
-------------------------------------------
|20 | 2 |1 |3 |
-------------------------------------------
|30 | 2 |2 |2 |
-------------------------------------------
|40 | 2 |3 |2 |
-------------------------------------------
|50 | 1 |
-----------------------
While searching stackoverflow i found this question for single column question and there is [this link for multiple columns] (get the count of each distinct value in "Multiple" columns) question. The answers from the second link (for the multiple coulmn's distinct count) is displayed under a single column and my requirement is i guess quite different from the answers posted there.
Thanks in advance
Your request is kind of odd. Are you sure you want that?
If so, this may help:
SET #x:=0,#y:=0,#m:=0,#n:=0;
SELECT
DISTINCT age,age_count, slot,slot_count
FROM (
SELECT
age, age_count, slot, slot_count
FROM (
SELECT
#x:=#x + 1 AS aid, age, COUNT(*) age_count
FROM
slots
GROUP BY age
) a
LEFT JOIN (
SELECT
#y:=#y + 1 AS sid, slot, COUNT(*) slot_count
FROM
slots
GROUP BY slot
) s ON a.aid = s.sid
UNION
SELECT
age, age_count, slot, slot_count
FROM (
SELECT
#m:=#m + 1 AS aid, slot, COUNT(*) slot_count
FROM
slots
GROUP BY slot
) a
LEFT JOIN (
SELECT
#n:=#n + 1 AS sid, age, COUNT(*) age_count
FROM
slots
GROUP BY age
) s ON a.aid = s.sid
) a
If you know for sure that you have more unique ages than unique slots , or opposite, you can get ride of messy union.

Resources