group by ID and delete the values - sql

I am modifying my description to make it more sense.
I want to select all the ID's which doesn't have value = Z2 ; How can I do that using sqlserver query ?
below is the data example
PK ID Value
1 1 x1
2 1 x2
3 1 x3
4 1 X4
5 2 X1
6 3 z2
7 2 Z2
8 4 X1
9 4 X2

EDIT: Since you clarified your question to just wanting to select the IDs that don't have z2 as a value, the query gets simpler. Just select all id's and remove those that have a z2 value using EXCEPT;
SELECT id FROM mytable
EXCEPT
SELECT id FROM mytable WHERE value='z2';
An SQLfiddle to test with.
(I'm assuming you want case insensitivity in this query)

DELETE FROM table where value <> 'z2';

You said in your question that you just want to select all the IDs which doesn't have value = Z2. So why would you want a DELETE query? A simple SELECT query like the following is supposed to give you the expected output:
SELECT ID
FROM Table
WHERE Value NOT IN ('Z2')
From the query, you can see that I have used an SQL clause - NOT IN, which will exclude certain values from specific column(s) while retrieving from your table. You don't need a DELETE query to view those IDs.
For better understanding, please refer to this link: SQL: NOT Condition

Related

SQL - How to filter out responses with no variation for survery collection to do multi-linear regression?

I'm new to SQL and I am trying to filter out responses with no variation for survery collection (invalid responses) to do multi-linear regression. Do take note that there is actually more than 100 records for this table and I have simplified it for the illustration.
Database: MySQL 8.0.30 : TLSv1.2 (TablePlus)
ID is the respondent number.
Variables - x1, x2, x3 is the independent variables.
Values - Survery response.
For example this is the current table I have:
ID
Variables
Values
1
x1
1
1
x2
1
1
x3
1
2
x1
2
2
x2
3
2
x3
4
3
x1
5
3
x2
5
3
x3
5
Scripts used:
SELECT ID, Variables, Values
FROM TableA
GROUP BY ID
I am trying to achieve the following table, where I only want to keep the records which have a variation in the responses:
ID
Variables
Values
2
x1
2
2
x2
3
2
x3
4
I have tried to use the functions WHERE, DISTINCT, WHERE NOT, HAVING, but I can't seem to get the results that I require, or showing blank most times (like the table below). If anyone is able to help, that would be most helpful.
ID
Variables
Values
Thank you very much!
Your problem has two parts so you are going to need to use a subquery for this.
you want to know which responses have variations. For this you'll want to group by the responses by the id, and then check that the responses that have the same id all have the same value, or not. For this you can select only those having more than one distinct value:
select `id`
from results
group by `id`
having count(distinct `values`) > 1
based on that you can just wrap it with a select to get all the fields that you want, ungrouped:
select *
from results
where `id` in (
select `id`
from results
group by `id`
having count(distinct `values`) > 1
)
This is MySQL syntax, but shouldn't have that many differences for main dbs
SQL Fiddle: http://sqlfiddle.com/#!9/a266f806/4/0
Hope that helps
Try the following:
WITH ids_with_variations as
(
SELECT ID
,COUNT(DISTINCT [Values]) as unique_value_count
FROM TableA
GROUP BY ID
HAVING COUNT(DISTINCT [Values]) = 3 -- this assumes that you expect each ID to have exactly three responses
)
SELECT *
FROM TableA
WHERE ID IN (SELECT ID FROM ids_with_variations)
This is TSQL dialect. This also assumes that you expect exactly three variations in the value column.

SQL subqueries with 'exists' clause and multiple tables

sorry, not enough reputation to post images. I have 3 SQL tables:
x1: {'a':1,2,3,4,5},
x2: {'c':1,1,1,2,2,3,3, 'd':1,3,5,1,3,1,1},
x3: {'b':1,3,5}
The query is:
select a from x1
where not exists (
select * from x3
where not exists (
select *
from x2
where x1.a = x2.c and x3.b=x2.d
)
)
The result from the following query is '1', but I can't understand what are the steps taken to get to that result.
What is being returned in which subquery?
I will try to explain. Your query will fetch records from table a for which the result set of
is empty(ie is asserted by not exists)
Consider the data in the tables
The values in a are 1,2,3,45
Lets check for a=1
We got against a=1 with c=1 three records in Table x2
And for the 3 records all of the column d values are present in table x3. This means the output of the block will return empty for a=1 and therefore will be present in the final output.
Check for a=2, the possible values in d are 1 and 3 and as we got 5 in table x3 the query will return a non-empty result
Similarly for a=3 the inner query returns 3 and 5 from table x3
For a=45, as a doesnt exist in table x2,all of the records table x3 gets returned -> 1,3,5
Therefore the only a which satisfy the empty result set is a=1 which is the answer.

SQL Update table with all corresponding data from another table concatenated?

Running PostgreSQL 12.4. I am trying to accomplish this but the syntax given there doesn't seem to be working on psql, and I could not find another approach.
I have the following data:
Table 1
ID Trait
1 X
1 Y
1 Z
2 A
2 B
Table 2
ID Traits, Listed
1
2
3
4
I would like to create the following result:
Table 2
ID Traits, Listed
1 X + Y + Z
2 A + B
Concatenating with + would be ideal, as some traits have inherent commas.
Thank you for any help!
Try something like:
update table2
SET traits = agg.t
FROM
(select id,string_agg(trait, ',') t from table1 group by id) agg
where
table2.id = agg.id;
dbfiddle
Concatenating with + would be ideal, as some traits have inherent commas.
You can use whatever delimiter you like (just change the second argument to string_agg).

Oracle query to link records from same table which maps to mapping table

Apologies for the horrible question title,not sure how to articulate it better.
So to start out.
**Table Dummy_Table**
id description filter_key
1 Test Record1 filterkey1
2 Test Record2 filterkey1
3 Test Record1 filterkey2
4 Test Record2 filterkey2
The records with filterkey1 map to a table like this
**Table Mapping_table**
Dummy_Table_id someother_key (one(Dummy_Table_id) to many(someother_key)
1 x
1 y
1 z
1 r
2 y
2 r
Now : In a query I map the id's to each other in the Dummy_Table using the description,so I end up with a resultset like this
id_for_filter_key1 id_for_filterkey2
1 3
2 4
Ok,thats all good and well,it's the next step I'm having a issue with.I need to add records to Table Mapping_table which should end up looking like this
**Table Mapping_table**
Dummy_Table_id someother_key
3 x
3 y
3 z
3 r
4 y
4 r
So in essence whatever the id is for filterKey1 I would like to apply it's someother_key to the id's with filterkey2 (filterKey1 and filterkey2 relate to each other with their descriptions)
Now I don't know if I'm over complicating this.I'll tell you what my problem is.
I have records in the database with filterkey1 which map to the mapping table.Afterwords I added the records with filterkey2.These rows are duplicates just with another filter key.Now I need to apply the same mappings to the records with filterkey2
Changing the table structure is not a option atm.I need to give the DBA a insert query to achieve this.
Many thanks in advance.
This query gives missing values:
SELECT d.id_for_filterkey2, m.someother_key
FROM Mapping_table m
JOIN Dummy_Table d ON m.Dummy_Table_id = d.id_for_filter_key1
Demo: http://sqlfiddle.com/#!4/61ddfe/2
When we have missing values, then we can merge them into Mapping_table:
MERGE INTO Mapping_table m
USING( copy-the-above-query-and-paste-it-here) x
ON (x.id_for_filterkey2 = m.Dummy_Table_id)
WHEN NOT MATCHED THEN
INSERT( Dummy_Table_id, someother_key )
VALUES( x.id_for_filterkey2, x.someother_key );
Demo: http://sqlfiddle.com/#!4/d74304/3

Finding contiguous regions in a sorted MS Access query

I am a long time fan of Stack Overflow but I've come across a problem that I haven't found addressed yet and need some expert help.
I have a query that is sorted chronologically with a date-time compound key (unique, never deleted) and several pieces of data. What I want to know is if there is a way to find the start (or end) of a region where a value changes? I.E.
DateTime someVal1 someVal2 someVal3 target
1 3 4 A
1 2 4 A
1 3 4 A
1 2 4 B
1 2 5 B
1 2 5 A
and my query returns rows 1, 4 and 6. It finds the change in col 5 from A to B and then from B back to A? I have tried the find duplicates method and using min and max in the totals property however it gives me the first and last overall instead of the local max and min? Any similar problems?
I didn't see any purpose for the someVal1, someVal2, and someVal3 fields, so I left them out. I used an autonumber as the primary key instead of your date/time field; but this approach should also work with your date/time primary key. This is the data in my version of your table.
pkey_field target
1 A
2 A
3 A
4 B
5 B
6 A
I used a correlated subquery to find the previous pkey_field value for each row.
SELECT
m.pkey_field,
m.target,
(SELECT Max(pkey_field)
FROM YourTable
WHERE pkey_field < m.pkey_field)
AS prev_pkey_field
FROM YourTable AS m;
Then put that in a subquery which I joined to another copy of the base table.
SELECT
sub.pkey_field,
sub.target,
sub.prev_pkey_field,
prev.target AS prev_target
FROM
(SELECT
m.pkey_field,
m.target,
(SELECT Max(pkey_field)
FROM YourTable
WHERE pkey_field < m.pkey_field)
AS prev_pkey_field
FROM YourTable AS m) AS sub
LEFT JOIN YourTable AS prev
ON sub.prev_pkey_field = prev.pkey_field
WHERE
sub.prev_pkey_field Is Null
OR prev.target <> sub.target;
This is the output from that final query.
pkey_field target prev_pkey_field prev_target
1 A
4 B 3 A
6 A 5 B
Here is a first attempt,
SELECT t1.Row, t1.target
FROM t1 WHERE (((t1.target)<>NZ((SELECT TOP 1 t2.target FROM t1 AS t2 WHERE t2.DateTimeId<t1.DateTimeId ORDER BY t2.DateTimeId DESC),"X")));