Update Missing Values - sql

I have a dataset that looks like the following
|---------------------|------------------|------------------|
| RowID | UserID | Code |
|---------------------|------------------|------------------|
| 1 | 123 | 0 |
|---------------------|------------------|------------------|
| 2 | 123 | 0 |
|---------------------|------------------|------------------|
| 3 | 123 | 50 |
|---------------------|------------------|------------------|
| 4 | 456 | 0 |
|---------------------|------------------|------------------|
| 5 | 456 | 100 |
|---------------------|------------------|------------------|
I would like to update the 0s to the non 0 Code for each UserID. Can someone provide assistance with this?

One option uses an updateable common table expression and window functions:
with cte as (
select code, max(code) over(partition by userID) max_code
from mytable
)
update cte set code = max_code where code = 0

You can use a simple sub-query for this:
update MyTable set
/* If its possible that a user might have multiple Codes which are non-zero you adjust the sub-query to return the correct one */
Code = (select top 1 Code from MyTable T2 where Code != 0 and T2.UserID = MyTable.UserId)
where Code = 0

Related

How can I subtract two row's values within same column using sql query in access?

(query access)
This is the table structure:
+-----+--------+--------+
| id | name | sub1 |
+-----+--------+--------+
| 1 | ABC | 6.27% |
| 2 | ABC | 7.47% |
| 3 | PQR | 3.39% |
| 4 | PQR | 2.21% |
+-----+--------+--------+
I want to subtract Sub1
Output should be:
+-----+--------+---------+------------------------------------+
| id | name | sub1 | |
+-----+--------+---------+------------------------------------+
| 1 | ABC | 6.27% | 0 First Rec no need Subtract |
| 2 | ABC | 7.47% | 1.2% <=(7.47-6.27) |
| 3 | PQR | 3.39% | 0 First Rec no need Subtract |
| 4 | PQR | 2.21% | -1.18% <=(2.21-3.39) |
+-----+--------+---------+------------------------------------+
Thank you so much.
If you can guarantee consecutive id values, then the following presents an alternative:
select t.*, nz(t.sub1-u.sub1,0) as sub2
from YourTable t left join YourTable u on t.name = u.name and t.id = u.id+1
Change YourTable to the name of your table.
This is painful, but you can do:
select t.*,
(select top 1 t2.sub1
from t as t2
where t2.name = t.name and t2.id < t.id
order by t2.id desc
) as prev_sub1
from t;
This gives the previous value or NULL for the first row. You can just use - for the subtraction.
An index on (name, id) would help a bit with performance. However, if you can upgrade to a better database, you can then just use lag().

Returning rows with the same ID but exclude some on second column

I've seen similar questions about but not quite hitting the nail on the head for what I need. Lets say I have a table.
+-----+-------+
| ID | Value |
+-----+-------+
| 123 | 1 |
| 123 | 2 |
| 123 | 3 |
| 456 | 1 |
| 456 | 2 |
| 456 | 4 |
| 789 | 1 |
| 789 | 2 |
+-----+-------+
I want to return DISTINCT IDs but exclude those that have a certain value. For example lets say I don't want any IDs that have a 3 as a value. My results should look like.
+-----+
| ID |
+-----+
| 456 |
| 789 |
+-----+
I hope this makes sense. If more information is needed please ask and if this has been answered before please point me in the right direction. Thanks.
You can use group by and having:
select id
from t
group by id
having sum(case when value = 3 then 1 else 0 end) = 0;
The having clause counts the number of "3"s for each id. The = 0 returns only returns groups where the count is 0 (i.e. there are no "3"s).
You can use not exists :
select distinct t.id
from table t
where not exists (select 1 from table t1 where t1.id = t.id and t1.value = 3);
Try this:
select id from tablename
group by id
having (case when value=3 then 1 else 0 end)=0
You can also use EXCEPT for comparing following two data sets that will give the desired result set
select distinct Id from ValuesTbl
except
select Id from ValuesTbl where Value = 3

SQL select multiple values present in multiple columns

I have two tables DiagnosisCodes and DiagnosisConditions as shown below. I need to find the members(IDs) who have a combination of Hypertension and Diabetes. The problem here is the DiagnosisCodes are spread across 10 columns. How do I check if the member qualifies for both conditions
DiagnosisCodes
+----+-------+-------+-------+-----+--------+
| ID | Diag1 | Diag2 | Diag3 | ... | Diag10 |
+----+-------+-------+-------+-----+--------+
| A | 2502 | 2593 | NULL | ... | NULL |
| B | 2F93 | 2509 | 2593 | ... | NULL |
| C | C257 | 2509 | C6375 | ... | NULL |
+----+-------+-------+-------+-----+--------+
DiagnosisConditions
+------+--------------+
| Code | Condition |
+------+--------------+
| 2502 | Hypertension |
| 2593 | Diabetes |
| 2509 | Diabetes |
| 2F93 | Hypertension |
| 2673 | HeartFailure |
+------+--------------+
Expected Result
+---------+
| Members |
+---------+
| A |
| B |
+---------+
How do I query to check Mulitple values which are present in Multiple columns. Do you suggest to use EXISTS?
SELECT DISTINCT id
FROM diagnosiscodes
WHERE ( diag1, diag2...diag10 ) IN (SELECT code
FROM diagnosiscondition
WHERE condition IN ( 'Hypertension','Diabetes' )
)
I would do this using group by and having:
select dc.id
from diagnosiscodes dc join
diagnosiscondistions dcon
on dcon.code in (dc.diag1, dc.diag2, . . . )
group by id
having sum(case when dcon.condition = 'diabetes' then 1 else 0 end) > 0 and
sum(case when dcon.condition = 'Hypertension' then 1 else 0 end) > 0;
Then, you should fix your data structure. Having separate columns with the same information distinguished by a number is usually a sign of a poor data structure. You should have a table, called somethhing like PatientDiagnoses with one row per patient and diagnosis.
Here is one way by unpivoting the data
SELECT DISTINCT id
FROM yourtable
CROSS apply (VALUES (Diag1),(Diag2),..(Diag10))tc(Diag)
WHERE Diag IN (SELECT code
FROM diagnosiscondition
WHERE condition IN ( 'Hypertension', 'Diabetes' ) group by code having count(distinct condition)=2)

SQL : Getting duplicate rows along with other variables

I am working on Terradata SQL. I would like to get the duplicate fields with their count and other variables as well. I can only find ways to get the count, but not exactly the variables as well.
Available input
+---------+----------+----------------------+
| id | name | Date |
+---------+----------+----------------------+
| 1 | abc | 21.03.2015 |
| 1 | def | 22.04.2015 |
| 2 | ajk | 22.03.2015 |
| 3 | ghi | 23.03.2015 |
| 3 | ghi | 23.03.2015 |
Expected output :
+---------+----------+----------------------+
| id | name | count | // Other fields
+---------+----------+----------------------+
| 1 | abc | 2 |
| 1 | def | 2 |
| 2 | ajk | 1 |
| 3 | ghi | 2 |
| 3 | ghi | 2 |
What am I looking for :
I am looking for all duplicate rows, where duplication is decided by ID and to retrieve the duplicate rows as well.
All I have till now is :
SELECT
id, name, other-variables, COUNT(*)
FROM
Table_NAME
GROUP BY
id, name
HAVING
COUNT(*) > 1
This is not showing correct data. Thank you.
You could use a window aggregate function, like this:
SELECT *
FROM (
SELECT id, name, other-variables,
COUNT(*) OVER (PARTITION BY id) AS duplicates
FROM users
) AS sub
WHERE duplicates > 1
Using a teradata extension to ISO SQL syntax, you can simplify the above to:
SELECT id, name, other-variables,
COUNT(*) OVER (PARTITION BY id) AS duplicates
FROM users
QUALIFY duplicates > 1
As an alternative to the accepted and perfectly correct answer, you can use:
SELECT {all your required 'variables' (they are not variables, but attributes)}
, cnt.Count_Dups
FROM Table_NAME TN
INNER JOIN (
SELECT id
, COUNT(1) Count_Dups
GROUP BY id
HAVING COUNT(1) > 1 -- If you want only duplicates
) cnt
ON cnt.id = TN.id
edit: According to your edit, duplicates are on id only. Edited my query accordingly.
try this,
SELECT
id, COUNT(id)
FROM
Table_NAME
GROUP BY
id
HAVING
COUNT(id) > 1

... where count(col) > 1

I have a table like this:
+-----+-----+-------+
| id | fk | value |
+-----+-----+-------+
| 0 | 1 | peter |
| 1 | 1 | josh |
| 3 | 2 | marc |
| ... | ... | ... |
I'd like now to get all entries which have more than one value.
The expected result would be:
+-----+-------+
| fk | count |
+-----+-------+
| 1 | 2 |
| ... | ... |
I tried to achieve that like this:
select fk, count(value) from table where count(value) > 1;
But Oracle didn't like it.
So I tried this...
select * from (
select fk, count(value) as cnt from table
) where cnt > 1;
...with no success.
Any ideas?
Use the having clause for comparing aggregates.
Also, you need to group by what you're aggregating against for the query to work correctly. The following is a start, but since you're missing a group by clause still it won't quite work. What exactly are you trying to count?
select fk, count(value)
from table
group by fk
having count(value) > 1;