Matching two variables to create a new ID - sql

I'm trying to create an SQL statement to match either an id number or a postcode and then assign a new id number
What I want to end up with is ‘newid’ that correctly recognizes that the first four records are the same person (even though the postcode for record 2 is different).
record id postcode newid
--------------------------
1 1 1 1
2 1 2 1
3 1 1 1
4 2 1 1
5 3 3 2
Any suggestions would be appreciated greatly.

Going based on your example:
SELECT RECORD,
(SELECT MIN (ID)
FROM users u2
WHERE users.id IN (u2.id, u2.postcode)
OR users.postcode in (u2.id, u2.postcode)
) AS newid
FROM users
This results with the following data:
RECORD NEWID
------------------
1 1
2 1
3 1
4 1
5 3
Here is the SQLFiddle

Related

Identify a FK which has the highest value from a list of values in its source table

I have following tables.
Part
id
name
1
Part 1
2
Part 2
3
Part 3
Operation
id
name
part_id
order
1
Op 1
1
10
2
Op 2
1
20
3
Op 3
1
30
4
Op 1
2
10
5
Op 2
2
20
6
Op 1
3
10
Lot
id
part_id
Operation_id
10
1
2
11
2
5
12
3
6
I am selecting the results from Lot table and I want to select a column last_Op which is based on the order value of the operation_id. If value of order for the operation_id is the highest for the respective part_id, return 1 else return 0
SELECT
id,
part_id,
operation_id,
last_Op
FROM Lot
expected result set based on the tables above.
id
part_id
operation_id
last_op
10
1
2
0
11
2
5
1
12
3
6
1
In above example, first row returns last_op = 0 because operation_id = 2 is associated with part_id = 1 and it has the highest order = 30. Since operation_id for this part is not pointing towards the highest order value, 0 is returned.
The other two rows return 1 because operation_id 5 and 6 are associated with part_id 2 and 3 respectively and they are pointing towards the highest 'order' value.
If value of order for the operation_id is the highest for the respective part_id, return 1 else return 0
This sounds like window functions will help:
select l.*,
(case when o.order = o.max_order then 1 else 0 end) as last_op
from lot l left join
(select o.*,
max(o.order) over (partition by o.part_id) as max_order
from operations o
) o
on l.operation_id = o.id;
Note: order is a very poor name for a column because it is a SQL keyword.

SQL Access Create / Update / Delete table based on query

I want to populate table1 based on a query. The table is used and information is added to the table by users (comment- field).
The result of the query:
TAG_ID CM_ID PROP_ID
1 1 5
1 2 3
2 1 2
2 2 20
Table1:
ID TAG_ID CM_ID PROP_ID COMMENT
1 1 1 5 comment 1 filled in by user
2 1 2 3 comment 1 filled in by user
3 2 1 2 comment 1 filled in by user
4 2 2 20 comment 1 filled in by user
The combination of TAG_ID / CM_ID / PROP_ID is unique.
If the combination does not exists => add
If the combination exists => leave as is (comment can be filled in by user and I don't want to loose the information)
if the combination is not present in the query => delete from table1
Thanks!

Update multiple rows in one query

My current table:
id | count | group_id
1 1 employee
2 2 employee
3 3 employee
4 4 employee
What I want:
id | count | group_id
1 4 employee
2 3 employee
3 2 employee
4 1 employee
What i've attempted
UPDATE table SET count = 4 WHERE count = 1 AND group_id='employee';
UPDATE table SET count = 3 WHERE count = 2 AND group_id='employee';
UPDATE table SET count = 2 WHERE count = 3 AND group_id='employee';
UPDATE table SET count = 1 WHERE count = 4 AND group_id='employee';
For obvious reason this does not work because it executes each query row by row, so my result is wrong. I think i'm looking for a way of updating multiple tables with one query?
This specific case can be solved like this:
UPDATE table SET count = 5 - count
WHERE count between 1 and 4 AND group_id= 'employee';
A more general solution, use a CASE expression:
UPDATE table SET count = case count when 4 then 1
when 3 then 2
when 2 then 3
when 1 then 4
end
WHERE count between 1 and 4 AND group_id = 'employee';

Can't figure out correct SQL query for historical table records

I'm trying for hours to find out the correct SQL query to select the latest historcal record from a table (in MySQL).
In my application I'd like to keep a history of every data modification. So my idea was, instead to make an UPDATE to an existing record, I'd rather make an INSERT of a new record. Additionally there is a revision counter, which gets increased with each record modification.
This is my table:
uid rid created_by deleted revision username password admin
1 1 0 0 0 stefan abcdefg 1
2 2 1 0 0 maria bcdefgh 1
3 3 1 0 0 carl cdefghi 0
4 4 1 0 0 SUSANN ABC123 0
5 4 1 0 1 SUSANN 123ABC 0
6 4 1 0 2 SUSANN 123ABC 1
7 4 1 1 3 SUSANN 123ABC 1
Note the rows with uid 4 to 7 are actually the same record, namely of "SUSANN". Row 4 is the initial row. Row 5 modified tha password, row 6 modifies the admin-flag, row 7 modified the deleted-flag.
uid is an auto-incrementor and identifies the row in the table for internal purposes. rid is the actual record-ID.
Now. Selecting the most current revision of a single record could be done this way:
SELECT * FROM table
WHERE rid=4
ORDER BY revision DESC
LIMIT 1
My problem is selecting a list of all the latest revision of all logins: Based on the sample data the result set should be:
uid rid created_by deleted revision username password admin
1 1 0 0 0 stefan abcdefg 1
2 2 1 0 0 maria bcdefgh 1
3 3 1 0 0 carl cdefghi 0
7 4 1 1 3 SUSANN 123ABC 1
Could someone point me in the right direction. I think the right keywords would be sufficient already. From there I could probably figure out a way.
Thanks.
This should work:
SELECT t.*
FROM table t
JOIN (SELECT rid, MAX(revision) MaxRevision FROM table GROUP BY rid) mt
ON t.rid = mt.rid AND t.revision = mt.MaxRevision

SQL: Need to create two unique records for each single record

The simple question is how can you take a set of records with a PK and create exactly two records for each source with a slightly altered key for the duplicate? In other words, I take 4000 records and produce 8000 records where 4000 are identical and the other 4000 have a slightly altered key. I cannot do a union because this is essentially two selects (long story).
The rest gets complicated, but maybe necessary to provide examples.
This is my original set (it contains over 4000 records)
dateGroup areaGroup itemID editionID
1 1 1 1
1 1 1 2
1 2 1 1
1 2 2 1
2 1 1 1
2 1 1 2
2 2 1 1
2 2 1 2
For each record I need to create a duplicate record ganging the areaGroups together under '0', then create a comma separated list of original areaGroups as a separate field. (The "why" is some dumb programmer (me) made a mistake about 15 years ago.) I can renumber the editionIDs as necessary, but the original and duplicate record must have the same editionID (thus why a union wouldn't work). The PK remains the same as above (all fields)
dateGroup areaGroup itemID editionID aGroups
1 0 1 1 1
1 0 1 2 1
1 0 1 1 2 // Duplicate (EditionID)
1 0 2 1 2
2 0 1 1 1
2 0 1 2 1
2 0 1 1 2 // Duplicate (EditionID)
2 0 1 2 2
The end result would renumber the editionID as needed to make the record unique.
dateGroup areaGroup itemID editionID aGroups (EditionID is what is altered)
1 0 1 1 1
1 0 1 2 1
1 0 1 2 2 1 changed to 2 (one more than row 1)
1 0 2 1 2
2 0 1 1 1
2 0 1 2 1
2 0 1 2 2 1 changed to 2 (one more than row 1)
2 0 1 2 2
1 1 1 1
1 1 1 2
1 2 1 2 1 changed to 2 (editionID) to match
1 2 2 1
2 1 1 1
2 1 1 2
2 2 1 2 1 changed to 2 to match above
2 2 1 2
I know you could calculate the editionID like a row rank like so:
select row_number() over (
partition by dateGroup, itemID
order by dateGroup, itemID) as editionID
So all I need is to know how to duplicate the records from a single set
do a cross join on a derived table:
( select 1 as aGroups union all select 2 )
I'd create a temporary table with duplicates and their count.
Then I'd filter the original table to have only unique rows, and insert another row for each row in the temporary table, incrementing their editionID.
In MySQL, I'd use user #variables; not sure about MS SQL.
Did you try UNION ALL instead of just UNION
UDPATE perhaps I misunderstood the problem and I thought you were having a problem with the union loosing the duplicates.
If the problem is that you want to do a row_number over a union why don't you do somthing like
select row_number() over (
partition by dateGroup, itemID
order by dateGroup, itemID) as editionID
FROM
(
SELECT
dateGroup, itemID
FROM TableA
UNION ALL
SELECT
dateGroup, itemID
FROM TableB
) Data