T-SQL Query comparing Member counts between 2 tables - sql-server

TABLE 1: Data sent to vendor
| MemberID | FirstName | LastName | Etc |
| :------: | :-------: | :------: | :-: |
| 1 | John | Smith | Etc |
| 2 | Jane | Doe | Etc |
| 3 | Dan | Laren | Etc |
TABLE 2: Data returned from vendor
| MemberID | FirstName | LastName | Etc |
| :------: | :-------: | :------: | :-: |
| 1 | John | Smith | Etc |
| 2 | Jane | Doe | Etc |
| 3 | Dan | Laren | Etc |
We send data to a vendor which is used for their matching algorithm and they return the data with new information. The members are matched with a MemberID data element. How would I write a query which shows me which MemberIDs we sent to the vendor but the vendor didn't return?

NOT EXITS would be my first choice here.
Example
SELECT *
FROM Table1 A
WHERE NOT EXISTS (SELECT 1
FROM Table2 B
WHERE A.MemberID = B.MemberID )

SELECT MemberID
FROM Table1
WHERE MemberID NOT IN (SELECT MemberID FROM Table2)

Using EXCEPT is one option.
SELECT sent.[MemberID] FROM Tbl1_SentToVendor sent
EXCEPT
SELECT recv.[MemberID] FROM Tbl2_ReturnedFromVendor recv
This is just on MemberID, but the "EXCEPT" syntax can also support additional columns (e.g., in case you want to filter out data that may be the same as what you already have.)

Related

Update table combining rows based on the same column value

I'm having a table called table such that:
| id | name | city |
|----|-------|---------|
| 0 | Rose | Madrid |
| 1 | Alex | Lima |
| 2 | Rose | Sidney |
| 3 | Mario | Glasgow |
And I need to UPDATE the table so that two rows sharing the same name combined into a new one and deleted.
| id | name | city |
|----|-------|----------------|
| 1 | Alex | Lima |
| 3 | Mario | Glasgow |
| 4 | Rose | Madrid, Sidney |
I don't care if it has to be done in several SQL statements.
So far all I've done is to list the rows that are affected by this.
SELECT *
FROM table
WHERE name IN (
SELECT name
FROM table
GROUP BY name
HAVING COUNT(*) > 1
);
Assuming that id is auto increment primary key, you need an INSERT and a DELETE statement:
insert into tablename(name, city)
select name, group_concat(city, ',')
from tablename
group by name
having count(*) > 1;
delete from tablename
where instr(name, ',') = 0
and exists (
select 1 from tablename t
where t.id <> tablename.id and t.name = tablename.name
and ',' || t.city || ',' like '%,' || tablename.city || ',%'
);
See the demo.
Results:
| id | name | city |
| --- | ----- | ------------- |
| 1 | Alex | Lima |
| 3 | Mario | Glasgow |
| 4 | Rose | Madrid,Sidney |

Track changes made in a record and get the version of the record at the given point of time in SQL Server

I need to track chages made in a record and able to get the any version of the record at given point of time.
Consider, I have the following contact table.
--------------------------
| contact |
--------------------------
| id |
| name |
| phone |
| email |
| city |
| country |
| create_by |
| created_at |
--------------------------
I want to achieve following things on the above table.
I want to track all the changes made in the records over the time.
I want to find the version of the record at the given point of time.
The original record should stay as it is (without any update).
For example,
So, I have created following table to track all the changes.
--------------------------
| contact_history |
--------------------------
| contact_id |
| field_name |
| old_value |
| new_value |
| modified_by |
| modified_at |
--------------------------
With this data model,
To create a new contact record, we will create the record in the contact table.
To Update a record, we will create a new record in the contact_history record with the field name, new value, current time and who modified the record.
In this way I can able to track, what change was made and who made the change and the same time the original record will stay as it is without any change.
What I am trying to achieve is to find the version of all the contact records at a given point of time.
For example, consider the following record.
Contact table
------------------------------------------------------------------------------------------------
| id | name | phone | email | city | country | created_by | created_at |
------------------------------------------------------------------------------------------------
| 1 | Steve | 1111111 | steve#abc.com | NY | USA | John | 2019-04-01 13:17:49.417 |
------------------------------------------------------------------------------------------------
Each update will be created as a history record in the contact_history table.
contact_history
-------------------------------------------------------------------------------------------------------
| contact_id | field_name | old_value | new_value | modified_at | modified_by |
-------------------------------------------------------------------------------------------------------
| 1 | email | steve#abc.com | steve#changed.com | 2019-04-02 08:19:49.213 | Arnold |
| 2 | city | NY | LA | 2019-04-03 12:48:37.568 | John |
| 3 | city | LA | SF | 2019-04-04 25:25:19.715 | John |
-------------------------------------------------------------------------------------------------------
When I need the version of the contact record before 2019-04-02 I should able to get the following,
------------------------------------------------------------------------------------------------
| id | name | phone | email | city | country | created_by | created_at |
------------------------------------------------------------------------------------------------
| 1 | Steve | 1111111 | steve#abc.com | NY | USA | John | 2019-04-01 13:17:49.417 |
------------------------------------------------------------------------------------------------
When I need the version of the contact record before 2019-04-03 I should able to get the following,
----------------------------------------------------------------------------------------------------
| id | name | phone | email | city | country | created_by | created_at |
----------------------------------------------------------------------------------------------------
| 1 | Steve | 1111111 | steve#changed.com | NY | USA | John | 2019-04-01 13:17:49.417 |
----------------------------------------------------------------------------------------------------
When I wanted the latest version of the same record I should able to get,
----------------------------------------------------------------------------------------------------
| id | name | phone | email | city | country | created_by | created_at |
----------------------------------------------------------------------------------------------------
| 1 | Steve | 1111111 | steve#changed.com | SF | USA | John | 2019-04-01 13:17:49.417 |
----------------------------------------------------------------------------------------------------
The example is given for only one record. It can be applicable for multiple contact records.
How can I write a efficient query to achieve this in SQL Server.
Simple. Use a TOP 1 query to get the most recent record before the date you want to filter on.
Unfortunately, due to the data model you've chosen to use, you'll need to do a TOP 1 subquery for every field in your result set that can be in your history table.
SELECT id,
(SELECT TOP 1 new_value ... WHERE field_name='Name' ... ) AS Name,
etc...

how to draw data from multiple tables?

I have 2 different tables. I need to get a name from the TMK table in table 1 as below, and I need to bring the total number from my 2nd table. I can't write join. can u help me
TMK Table;
| tmkName |
| George |
| Jacob |
flowNewStatus Table;
|statusId|
| 1 |
| 2 |
if george has number 1 status i want this join
| tmkName | |statusId|
| George | | 1 |
Before getting to possible SQL queries... from the tables you show you'd need an additional table that associates the person to status, a join table. Essentially a TMK_status table:
TMK_status table
| personID | statusID |
|----------|----------|
| 1 | 1 |
| 2 | 3 |
| 3 | 1 |
Alternatively, the statusID could be stored as a column of TMK thus,
TMK table
| personID | tmkName | statusID |
|----------|----------|----------|
| 1 | George | 1 |
| 2 | Jacob | 3 |
If by "I can't write join", you mean you don't know how, check this answer: What is the difference between "INNER JOIN" and "OUTER JOIN"? - you will need an inner join.
If, on on the other hand, you mean you can't use join statements, then you could write a subselect statement. There could be other solutions but they depend on how you decide to join/relate the 2 tables.

T-SQL Query which only displays rows where the value in one column matches the value in another column on another row

Having exhausted my limited knowledge of tsql I hope someone may be able to help?
I have a table which holds relationship data such as ID, name, relationship and reciprocal relationship type, start and finish date etc.
Each row contains the Reciprocal ID for the other side of the relationship. See below.
From that I would like to present rows where the ID is equal to 1234 and 1236.
Thank you in advance for help with this.
Paul
+------+-------+------------+------------+----------+------------+---------+
| ID | Name | Start | Finish | Type | Recip Type | RecipID |
+------+-------+------------+------------+----------+------------+---------+
| 1234 | Joe | 01/05/2018 | | Father | Daughter | 1235 |
+------+-------+------------+------------+----------+------------+---------+
| 1235 | Emily | 01/05/2018 | | Daughter | Father | 1234 |
+------+-------+------------+------------+----------+------------+---------+
| 1236 | Susan | 01/09/2017 | 01/05/2018 | Visitor | Patient | 1237 |
+------+-------+------------+------------+----------+------------+---------+
| 1237 | Harry | 01/09/2017 | 01/05/2018 | Patient | Visitor | 1236 |
+------+-------+------------+------------+----------+------------+---------+
Are you looking for or:
select t.*
from t
where id in (1234, 1236) or recipid in (1234, 1236);
Perhaps this would do what you intend:
select t1.*
from table t1
where exists (select 1 from table t2 where t1.id = t2.recipid);
However, same could be also achieve via self join

SQL Server group and inverse

I'm stuck with an easy SQL Server thing for my own personal project.
I have a table X:
| Name | Lecture | Points |
|:-----------|------------:|:------------:|
| John | Math | 2
| John | Bio | 5
| Tom | Physics | 8
| Tom | Math | 2
| Bob | Physics | 1
| Bob | Bio | 6
And I want to group by Name and to put all points I one row for each person:
| Name | Math | Bio | Physics |
|:-----------|------:|:----:|:-------:|
| John | 2 | 5 | NULL
| Tom | 2 | NULL | 8
| Bob | NULL | 6 | 1
I tried doing this:
SELECT Name, ? AS Math, ? AS Bio, ? AS Physics
FROM X
GROUP BY Name
but I don't know what to put instead of "?". How can I do that ?
You need a pivot table and you need to know the values, unless you want to use dynamic sql (not recommended unless absolutely necessary):
SELECT Name,
ISNULL([Math], 0) as [Math],
ISNULL([Bio], 0) as [Bio],
ISNULL([Physics], 0) as [Physics]
FROM
(
SELECT Name, Lecture, SUM(Points)
FROM Table X
GROUP BY Name, Lecture
) as t1
PIVOT (SUM([Points]) for [Lecture] in ([Math], [Bio], [Physics])) as t2

Resources