Check for same character value in column - sql

I'm trying to verify when a column has all the same values for the same group. Here is a sample of my table data:
So using this data, for example. I want to check to see if all values of Status is the same for every row with the same TPID. So TPID 60210 should result with True since both items have a Status of A. However, TPID 60061 should result in false since two of the Line_Item show A and the rest P.
I intend to update a different table using this information, setting its status using a CASE statement. But I'm at a loss how to check against this column to find the values I desire.

;WITH CTE_Count
AS
(
SELECT TPID, COUNT(DISTINCT Status) CNT
FROM TableName
GROUP BY TPID
)
UPDATE AnotherTableName
SET ColumnName = (
CASE WHEN CTE_Count.CNT = 1 -- all row has same status
THEN SomeValue
ELSE SomeOtherValue END
)
FROM AnotherTableName
INNER JOIN CTE_Count ON ...

Related

Exclude rows where ID is duplicated but 3rd column has "unknown

I have this dataset where there are rows with duplicate personIDs but different pcpgrouper2. I only want to exclude "Unknown" where there are more than 1 of the same PersonID and one of them is "Unknown". If the ID has only one row with "Unknown" then keep that row.
Name
PersonID
PCPGrouper
ABBAN, AVRIL
1094893
Unknown
ABBIS,CHLOE
1114294
T Docs
ABBIS,CHLOE
1114294
Unknown
We can try using the following SQL query (assuming you are using SQL):
SELECT Name, PersonID, PCPGrouper
FROM yourTable t1
WHERE PCPGrouper != 'Unknown' OR
NOT EXISTS (
SELECT 1
FROM yourTable t2
WHERE t2.PersonID = t1.PersonID AND
t2.PCPGrouper != 'Unknown'
);
The above logic retains any person record whose grouper value is not unknown or is unknown but there is no other value.

Trying to INSERT to based on CASE statement with SELECT VALUE

I Have a list of of SpellIDs with corresponding M values.
Given by the statement
SELECT TOP(1000) Spell_ID, MAX(Episode_Order) as M
From [dbo].[Client_MidEssex_Inpatient_Episodes_Landing]
GROUP BY Spell_ID
output
What I want to is to INSERT on the Episode Order Column on my Inpatients_episodes_table, a value depending on the M column from the select statement, on the corresponding spell_IDs. (Each row has a spell ID and Episode order value)
The logic is:For each spell ID value in the table Check the corresponding spellID in the select statement and -> check M value. Then Compare M value from the select statement to the Episode Order value from the table. Based on this comparison, insert either a discharge or admittance code
I am trying to relate the select statement and the table both on spell_IDs, but I'm not too how.
So far I have this:
UPDATE Inpatient_Episodes_Landing SET Episode_Ward = Null;
INSERT INTO [dbo].[Inpatient_Episodes_Landing] ([Episode_Ward])
SELECT
(Case when Episode_Order=01 then Admission_Ward_Code
when Episode_Order = (SELECT Spell_ID, MAX(Episode_Order) as M
From [dbo].[Client_MidEssex_Inpatient_Episodes_Landing]
where Spell_ID = (select SpellID from [dbo].[Inpatient_Episodes_Landing])
GROUP BY Spell_ID ) then Discharge_Ward_Code
else Admission_Ward_Code
END)
FROM [dbo].[Client_MidEssex_Inpatient_Episodes_Landing]
Select TOP (1000) SpellID,Episode_Number,Episode_Ward from Inpatient_Episodes_Landing
Any help would be great, thank you!

How can I put a column in SQL that shows a 1 if the value in another column is unique and 0 if it's duplicate?

I would like to build a column that puts the value 1 if it's the first occurrence of a value in one row and 0 if it's not the first occurrence.
You could use a window function and CTE to assign a rownumber to each partition of "data" and then have flag set to 1 when rownumber is 1 else 0.
Rextester Demo
This assumes:
the filed to evaluate is called "Data"
the 1st entry isn't considered a duplicate where all others are. 1st is tricky here as we've not defined an order so the first entry the system encounters will be treated as non-duplicate; unless we further define the order by in the window function; that non-duplicate could change from run to run.
.
With CTE AS (SELECT Data, Row_Number() over (partition by Data order by Data) RN
FROM TableName T)
SELECT Data, case when RN = 1 then 1 else 0 end as Flg
FROM CTE
Returns something like this given my sample data used:
Data Flg
1 A 1
2 A 0
3 B 1
4 B 0
5 B 0
6 C 1
7 C 0
First of all it's not possible to automagically set and update this value in the table. They'd have to be recalculated after every modification to the table and calculated columns can't refer to other rows, or execute full queries.
You can use a window function like LAG to check if there's a previous value in a set according to the search order you provide exists or not, eg :
declare #t table (data varchar(10))
insert into #t
values ('A'),
('B'),
('A'),
('B'),
('B'),
('C'),
('C')
SELECT
Data,
iif( lag(1) over (partition by Data order by Data) is null,1,0) as Value
FROM #t
This will return :
Data Value
A 1
A 0
B 1
B 0
B 0
C 1
C 0
lag(1) over (partition by Data order by Data) partitions the rows by the values in the data column and sorts them by the same value, essentially producing a random order. It then returns the "previous" value for that partition. For the first row, there is none and LAG returns null.
iif( ... is null,1,0) as Value checks the result and returns 1 if it's null, 0 otherwise.
If you want to store the changes to the table, you can use an updatable CTE :
declare #t table (data varchar(10),value bit)
insert into #t(data)
values ('A'),
('B'),
('A'),
('B'),
('B'),
('C'),
('C');
with x as ( SELECT
Data,value,
iif( lag(1) over (partition by Data order by Data) is null,1,0) as Val
FROM #t)
update x
set value=val
from #t;
select *
from #t
order by data
You could use a trigger on INSERT, UPDATE, DELETE to run that query on every modification and update the table. It would be better though to make all modifications and execute UPDATE only at the end
SQL table represent unordered sets. Your table does not have enough information to answer this question, once the table has been created.
If you do have such a table, you can use a query such as this to assign the value:
select value,
(case when row_number() over (partition by value order by ?) = 1
then 1 else 0
end) as flag
from t;
The ? is a placeholder for a column such as createdAt or id, which specifies the ordering of the values in the table.
If you don't have a column that specifies the ordering, you could do this with a trigger that checks if the value already exists. However, rather than writing a trigger, I would suggest creating the table with an identity() column or createdAt column (or both) to capture insertion order.

I am trying to return a certain values in each row which depend on whether different values in that row are already in a different table

I'm still a n00b at SQL and am running into a snag. What I have is an initial selection of certain IDs into a temp table based upon certain conditions:
SELECT DISTINCT ID
INTO #TEMPTABLE
FROM ICC
WHERE ICC_Code = 1 AND ICC_State = 'CA'
Later in the query I SELECT a different and much longer listing of IDs along with other data from other tables. That SELECT is about 20 columns wide and is my result set. What I would like to be able to do is add an extra column to that result set with each value of that column either TRUE or FALSE. If the ID in the row is in #TEMPTABLE the value of the additional column should read TRUE. If not, FALSE. This way the added column will ready TRUE or FALSE on each row, depending on if the ID in each row is in #TEMPTABLE.
The second SELECT would be something like:
SELECT ID,
ColumnA,
ColumnB,
...
NEWCOLUMN
FROM ...
NEWCOLUMN's value for each row would depend on whether the ID in that row returned is in #TEMPTABLE.
Does anyone have any advice here?
Thank you,
Matt
If you left join to the #TEMPTABLE you'll get a NULL where the ID's don't exist
SELECT ID,
ColumnA,
ColumnB,
...
T.ID IS NOT NULL AS NEWCOLUMN -- Gives 1 or 0 or True/false as a bit
FROM ... X
LEFT JOIN #TEMPTABLE T
ON T.ID = X.ID -- DEFINE how the two rows can be related unquiley
You need to LEFT JOIN your results query to #TEMPTABLE ON ID, this will give you the ID if there is one and NULL if there isn't, if you want 1 or 0 this would do it (For SQL Server) ISNULL(#TEMPTABLE.ID,0)<>0.
A few notes on coding for performance:
By definition an ID column is unique so the DISTINCT is redundant and causes unnecisary processing (unless it is an ID from another table)
Why would you store this to a temporary table rather than just using it in the query directly?
You could use a union and a subquery.
Select . . . . , 'TRUE'
From . . .
Where ID in
(Select id FROM #temptable)
UNION
SELECT . . . , 'FALSE'
FROM . . .
WHERE ID NOT in
(Select id FROM #temptable)
So the top part, SELECT ... FROM ... WHERE ID IN (Subquery), does a SELECT if the ID is in your temptable.
The bottom part does a SELECT if the ID is not in the temptable.
The UNION operator joins the two results nicely, since both SELECT statements will return the same number of columns.
To expand on what someone else was saying with Union, just do something like so
SELECT id, TRUE AS myColumn FROM `table1`
UNION
SELECT id, FALSE AS myColumn FROM `table2`

Count(*) with 0 for boolean field

Let's say I have a boolean field in a database table and I want to get a tally of how many are 1 and how many are 0. Currently I am doing:
SELECT 'yes' AS result, COUNT( * ) AS num
FROM `table`
WHERE field = 1
UNION
SELECT 'no' AS result, COUNT( * ) AS num
FROM `table`
WHERE field = 0;
Is there an easier way to get the result so that even if there are no false values I will still get:
----------
|yes | 3 |
|no | 0 |
----------
One way would be to outer join onto a lookup table. So, create a lookup table that maps field values to names:
create table field_lookup (
field int,
description varchar(3)
)
and populate it
insert into field_lookup values (0, 'no')
insert into field_lookup values (1, 'yes')
now the next bit depends on your SQL vendor, the following has some Sybase (or SQL Server) specific bits (the outer join syntax and isnull to convert nulls to zero):
select description, isnull(num,0)
from (select field, count(*) num from `table` group by field) d, field_lookup fl
where d.field =* fl.field
you are on the right track, but the first answer will not be correct. Here is a solution that will give you Yes and No even if there is no "No" in the table:
SELECT 'Yes', (SELECT COUNT(*) FROM Tablename WHERE Field <> 0)
UNION ALL
SELECT 'No', (SELECT COUNT(*) FROM tablename WHERE Field = 0)
Be aware that I've checked Yes as <> 0 because some front end systems that uses SQL Server as backend server, uses -1 and 1 as yes.
Regards
Arild
This will result in two columns:
SELECT SUM(field) AS yes, COUNT(*) - SUM(field) AS no FROM table
Because there aren't any existing values for false, if you want to see a summary value for it - you need to LEFT JOIN to a table or derived table/inline view that does. Assuming there's no TYPE_CODES table to lookup the values, use:
SELECT x.desc_value AS result,
COALESCE(COUNT(t.field), 0) AS num
FROM (SELECT 1 AS value, 'yes' AS desc_value
UNION ALL
SELECT 2, 'no') x
LEFT JOIN TABLE t ON t.field = x.value
GROUP BY x.desc_value
SELECT COUNT(*) count, field FROM table GROUP BY field;
Not exactly same output format, but it's the same data you get back.
If one of them has none, you won't get that rows back, but that should be easy enough to check for in your code.