Find which column differs between 2 rows? - sql

We are using audit tables for each operational table, which stores the previous value of its operational equivalent plus change date, change type (UPDATE or DELETE) and its own auto incremental Primary Key.
So, for a table Users with columns UserID, Name, Email there would be a table xUsers with columns ID, OpererationType, OperationDate, UserID, Name, Email.
See that the xTable contains every column that its 'parent' does with 3 extra fields. This pattern is repeated for all tables used by our system.
table Users:
UserID int
Name nvarchar
Email nvarchar
table xUsers:
xUserID int
OpererationType int
OperationDate datetime
UserID int
Name nvarchar
Email nvarchar
Now, my question:
If I have a certain UserID, for which there is 2 entries in the xUsers table when the email was changed twice,
how would I construct a query that identifies which columns (can be more than 1) differ between the two rows in the audit table?

If I'm understanding this correctly, you'd like to create a query passing in the UserID as a parameter, which I'll call #UserID for the following example.
This query will select all rows from xUsers joined onto itself where there is a difference in a non-UserID column, using a series of case statements (one per column) to pull out specifically which columns differ.
SELECT *
, CASE
WHEN a.OperationType <> b.OperationType
THEN 1
ELSE 0
END AS OperationTypeDiffers
, CASE
WHEN a.OperationDate <> b.OperationDate
THEN 1
ELSE 0
END AS OperationDateDiffers
FROM xUsers a
JOIN xUsers b
ON a.xUserID < b.xUserID
AND a.UserID = b.UserID
AND (a.OperationType <> b.OperationType
OR a.OperationDate <> b.OperationDate) -- etc.
WHERE a.UserID = #UserID

You can put the rows of xUsers in a temporary table and then make a while cycle to go for each one and compare the results.
OR
You can do some dynamic SQL and use sysobjects and syscolumns tables to compare each result. It would be more dynamic and then it would be easy to implement for other tables.

Related

Complex SQL query Help Pls

Well I have 2 Table named 'A' and 'B'
One of the tables(A) include many records in this records ı have a column holding 'SENDER_CONTACT_NUMBER' it can be too many invoice from same sender.
Other table Holding 'SENDER_CONTACT_NUMBER' and 'STATUS'(1 - is active )( 0 - is not active) so in this table 'SENDER_CONTACT_NUMBER' is unique and I want make sql query that Union 2 tables 'SENDER_CONTACT_NUMBER' and I want to create 2. column for each 'SENDER_CONTACT_NUMBER' And I want to take Counts in table A (I solve the first part but second is real problem to me cause B table 'SENDER_CONTACT_NUMBER' may not be in A table so in this case I couldn't show counts :(
TABLE A
INVOICE_TYPE_CODE varchar no
SENDER_CONTACT_NUMBER varchar no
SENDER_IDENTIFIER varchar no
SENDER_NAME varchar no
RECEIVER_CONTACT varchar no
RECEIVER_IDENTIFIER varchar no
RECEIVER_NAME varchar no
TABLE B
SENDER_CONTACT_NUMBER varchar no
URUN varchar no
BASTAR char no
BITTAR char no
STATUS smallint no
Result that I want to see
COLUMN 1
Union SENDER_CONTACT_NUMBER LIST BY STATUS=1
COLUMN 2
For each record in sender_contact_number at column 1 show counts in a if there is no record put 0
enter image description here
Assuming you want a count of the number of occurrences of each SENDER_CONTACT_NUMBER in table A, including records from B that have no corresponding record in A, then this should work:
SELECT B.SENDER_CONTACT_NUMER, COUNT(A.INVOICE_TYPE_CODE) AS Invoices
FROM B
LEFT JOIN A ON B.SENDER_CONTACT_NUMER = A.SENDER_CONTACT_NUMER
WHERE B.STATUS = 1 -- Only include active contacts

How to populate data from a table, depending upon another table

My question is super straight,
I have a table naming FAQ_MASTER having data of faqs
I have another table naming FAQ_OVERRIDE having data of overrided faqs with foreign key company_id from different table
Now i want to populate data from FAQ_MASTER, if FAQ_OVERRIDE is not populating data depending upon the company_id fetched from session variable
if FAQ_OVERRIDE is populating data, then populating data from FAQ_MASTER is not required.
i want to run the query in postreSQL
What i have tried :
select
*
from
(
SELECT
distinct fm.faq_uid as faqUid,
case
when fm.qa_text is not null then fm.qa_text
else fm.qa_text
end as qaText,
case
when fm.sort_order is not null then fm.sort_order
else fm.sort_order
end as sortOrder,
fm.end_date as endDate
FROM rnr.faq_master fm
) faq_qry
left outer join rnr.company_faq_override fo on faq_qry.faqUid = fo.faq_override_uid and fo.mp_company_uid = 734
WHERE
faq_qry.endDate is null
AND
(
faq_qry.mp_company_uid is null or fo.mp_company_uid = 734
)
ORDER BY
faq_qry.sortOrder

Single SQL Query to validate input values

I have written a Stored procedure which has three argumets
#UserID1 BIGINT
#UserID2 BIGINT
#UserID3 BIGINT
What I want to achieve is to write a single SQL query against table dbo.aspnet_UsersInRoles column ID so that #UserID1, #UserID2, #UserID3 are present in ID column of dbo.aspnet_UsersInRoles.
For example, I have received three values in variables and I want to confirm they are part of Id column. i.e. ID column of table has values 1,2,3,4,5,6,7,8,9,10 and UserID1 is 2, UserID2 is 5 and UserID3 is 7. So it should give true else false.
I can implement using three different queries but I am not getting any clue to do it in a single query.
You should be able to use something like this:
SELECT CASE WHEN SUM( CASE
WHEN #UserID1 = ID THEN 1
WHEN #UserID2 = ID THEN 1
WHEN #UserID3 = ID THEN 1
ELSE 0
END ) = 3 THEN 1 ELSE 0 AS [AllThree]
FROM aspnet_UsersInRoles
(untested code)
...assuming that the ID column is unique. If all three IDs are in the table, then you should end up with a summed value of 3. This will allow you to process the table in a single pass, but you don't get the advantages of index lookups like you get in Upendra's answer.

What is wrong with this SQL statement for inserting concatenated IDS from a table into a field?

INSERT INTO Activity_Feed (userID,Type,DataIDs,PodID)
VALUES ( 1437
, 'eventattend'
, (SELECT LEFT(EventID, LEN(eventID) - 1 as nvarchar)
FROM (
SELECT EventiD + ', '
FROM events
FOR XML PATH ('')) c (EventID))
, 5)
Basically I want to take a bunch of IDs from a table and insert them as a comma delimited string into a varchar field.
E.g.
Activity_Feed (table)
activityID 1
userID 2
DataIDs 1,3,4,56,367 // This would be the (Select Ids FROM bit)
I want to take a bunch of RSVP IDs from a table and stick their IDs in the field...
To further explain I wanted to avoid normalizing the query because of the nature of this query. Let me know if I should still separate out the data...
The activity feed works like this...
I create a new entry in activity with a type of event_attending (which is an event I am attending.
I timestamp it, I enter the ID for the event in the dataIDs field any new activity matching event_attending in a 6 hour period fires an update record rather than insert
I keep the timestamp the same but update the ID's that are associated with that time period so basically update the IDs with the latest event attendance within that time period.
I thought normalizing seemed like overkill :D is there such thing as overkill with normalization?
Always normalize your database.
This is totally not wrong but very poor in database design.
Reasons why this is very poor:
hard to join tables
hard to find values
Why not create table like this,
Activity
ActivityID
ActivityName
Feed
FeedID
FeedName
Activity_Feed
FeedID
ActivityID
so Activity_Feed table will contain something like this
FeedID ActivityID
=====================
1 1
1 2
1 3
2 1
2 3
3 2
3 1
and you can now join the tables,
SELECT a.ActivityName, c.FeedName
FROM Activity a
INNER JOIN Activity_Feed b
ON a.ActivityID = b.ActivityID
INNER JOIN Feed c
ON b.FeedID = c.FeedID
-- WHERE a.ActivityName = 1 -- or something like this

SQL query to select * from table, but return ID column as looked-up usernames

I'm using Bugzilla, and I essentially want to SELECT * FROM bugs table in the "bugs" database. However, the "assigned_to" column actually contains integer values (IDs) instead of a string with the user name.
These IDs match primary keys in the "profiles" table (the "userid" column), and the string I want my query to return is actually stored in the "realname" column in that table.
How can I modify this query to capture all columns in "bugs," but perform a lookup on the assigned_to column and return usernames?
SELECT b.*, p.realname FROM bugs b
JOIN profiles p
ON b.assigned_to = p.userid