SQL Select from 1 table rows with 2 specific column value that are not equal - sql

I have a table
id number name update_date
1 123 asd 08.05.18
2 412 ddd 08.05.18
3 123 dsa 14.05.18
4 125 dsa 05.05.18
Whole table consist from that rows like that. I need to select row 1 and 3 because I need different update_dates but same number. How to do that? I need to see the changes from specific Number between 2 update dates 08.05.18 and 14.05.18. I have more update dates in my table.
I tried:
SELECT *
FROM legal_entity_history a
JOIN legal_entity_history b ON a.BIN = b.BIN
WHERE ( a.update_date <> b.update_date AND
a.update_date = "08.05.18" AND
b.update_date = "14.05.18" )

A relatively simple method is:
select leh.*
from legal_entity_history leh
where exists (select 1
from legal_entity_history leh2
where leh2.number = leh.number and leh2.update_date <> leh.update_date
);
For performance, you want an index on legal_entity_history(number, update_date).

TRY THIS: Assuming that same number may not appear more than once under same update_date, so, you can achieve that using GROUP BY with HAVING as below
SELECT t.*
FROM test t
INNER JOIN (SELECT number
FROM test
GROUP BY number
HAVING COUNT(DISTINCT update_date) > 1) t1 ON t1.number = t.number
OUTPUT:
id number name update_date
1 123 asd 08.05.18
3 123 dsa 14.05.18

Related

How to use multiple counts in where clause to compare data of a table in sql?

I want to compare data of a table with its other records. The count of rows with a specific condition has to match the count of rows without the where clause but on the same grouping.
Below is the table
-------------
id name time status
1 John 10 C
2 Alex 10 R
3 Dan 10 C
4 Tim 11 C
5 Tom 11 C
Output should be time = 11 as the count for grouping on time column is different when a where clause is added on status = 'C'
SELECT q1.time
FROM (SELECT time,
Count(id)
FROM table
GROUP BY time) AS q1
INNER JOIN (SELECT time,
Count(id)
FROM table
WHERE status = 'C'
GROUP BY time) AS q2
ON q1.time = q2.time
WHERE q1.count = q2.count
This is giving the desired output but is there a better and efficient way to get the desired result?
Are you looking for this :
select t.*
from table t
where not exists (select 1 from table t1 where t1.time = t.time and t1.status <> 'C');
However you can do :
select time
from table t
group by time
having sum (case when status <> 'c' then 1 else 0 end ) = 0;
If you want the times where the rows all satisfy the where clause, then in Postgres, you can express this as:
select time
from t
group by time
having count(*) = count(*) filter (where status = 'C');

How to update every rows which has a number greater than or equal to the joining table?

Here is an example of the tables I am joining together (note: the tables have the exact same schema but are in different databases, I am trying to combine them):
Database 1 Table
UniqID UniqID2 Number
100 150 1
100 151 2
Database 2 Table
UniqID UniqID2 Number
100 152 2
100 153 3
I am trying to merge Table2 into Table1 and I'm joining on Table1.UniqID = Table2.UniqID. I don't want any overlapping values in the Number column, this is what I want the result to look like:
Table 1
UniqID UniqID2 Number
100 150 1
100 151 2
100 152 3
100 153 4
This is the query I have so far, but it only updates the row in Table 2 where the Number = 2 and doesn't increment the Number = 3 row. How can I adjust my query to do so?
UPDATE db2
Set db2.Number = db2.Number +
(SELECT MAX(Number) FROM [Database 1]..db1 WHERE UniqID = db2.UniqID)
FROM [Database 2]..table db2
INNER JOIN [Database 1]..Table db1
ON db1.UniqID = db2.UniqID
AND db1.Number = db2.Number
And this is what my Database 2 Table results look like right now:
Database 2 Table
UniqID UniqID2 Number
100 152 3
100 153 3
Basically, the only difference is that I want the Number = 3 to be Number = 4 in the second column.
I think you want a union all query and insert:
insert into table1(UniqID, UniqID2, Number)
select t2.UniqID, t2.UniqID2,
(x.maxn + row_number() over (order by (select null) ))
from table2 t2 cross join
(select max(number) as maxn from table1) x;
A different appraoch could be
UPDATE t2
SET t2.Number = t1.T1Number + 1
FROM table2 t2
INNER JOIN (SELECT uniqid, uniqid2, number as T1Number from Table1
union
SELECT uniqid, uniqid2, number as T1Number from Table2
) t1
ON t1.uniqid = t2.uniqid and t1.UniqID2 = t2.UniqID2-1
one more approach which works in SQL 2012..
Demo here
;With cte
as
(select *
from
#t
union all
select *
from #t1
)
select uniqid,uniqid2,
case when lag(number) over (order by uniqid,uniqid2) is null then number
when lead(number) over (order by uniqid,uniqid2) is null
then number+1 else lead(number) over (order by uniqid,uniqid2) end as nextnumber
from cte

How can I select unique rows in a database over two columns?

I have found similar solutions online but none that I've been able to apply to my specific problem.
I'm trying to "unique-ify" data from one table to another. In my original table, data looks like the following:
USERIDP1 USERIDP2 QUALIFIER DATA
1 2 TRUE AB
1 2 CD
1 3 EF
1 3 GH
The user IDs are composed of two parts, USERIDP1 and USERIDP2 concatenated. I want to transfer all the rows that correspond to a user who has QUALIFIER=TRUE in ANY row they own, but ignore users who do not have a TRUE QUALIFIER in any of their rows.
To clarify, all of User 12's rows would be transferred, but not User 13's. The output would then look like:
USERIDP1 USERIDP2 QUALIFIER DATA
1 2 TRUE AB
1 2 CD
So basically, I need to find rows with distinct user ID components (involving two unique fields) that also possess a row with QUALIFIER=TRUE and copy all and only all of those users' rows.
Although this nested query will be very slow for large tables, this could do it.
SELECT DISTINCT X.USERIDP1, X.USERIDP2, X.QUALIFIER, X.DATA
FROM YOUR_TABLE_NAME AS X
WHERE EXISTS (SELECT 1 FROM YOUR_TABLE_NAME AS Y WHERE Y.USERIDP1 = X.USERIDP1
AND Y.USERIDP2 = X.USERIDP2 AND Y.QUALIFIER = TRUE)
It could be written as an inner join with itself too:
SELECT DISTINCT X.USERIDP1, X.USERIDP2, X.QUALIFIER, X.DATA
FROM YOUR_TABLE_NAME AS X
INNER JOIN YOUR_TABLE_NAME AS Y ON Y.USERIDP1 = X.USERIDP1
AND Y.USERIDP2 = X.USERIDP2 AND Y.QUALIFIER = TRUE
For a large table, create a new auxiliary table containing only USERIDP1 and USERIDP2 columns for rows that have QUALIFIER = TRUE and then join this table with your original table using inner join similar to the second option above. Remember to create appropriate indexes.
This should do the trick - if the id fields are stored as integers then you will need to convert / cast into Varchars
SELECT 1 as id1,2 as id2,'TRUE' as qualifier,'AB' as data into #sampled
UNION ALL SELECT 1,2,NULL,'CD'
UNION ALL SELECT 1,3,NULL,'EF'
UNION ALL SELECT 1,3,NULL,'GH'
;WITH data as
(
SELECT
id1
,id2
,qualifier
,data
,SUM(CASE WHEN qualifier = 'TRUE' THEN 1 ELSE 0 END)
OVER (PARTITION BY id1 + '' + id2) as num_qualifier
from #sampled
)
SELECT
id1
,id2
,qualifier
,data
from data
where num_qualifier > 0
Select *
from yourTable
INNER JOIN (Select UserIDP1, UserIDP2 FROM yourTable WHERE Qualifier=TRUE) B
ON yourTable.UserIDP1 = B.UserIDP1 and YourTable.UserIDP2 = B.UserIDP2
How about a subquery as a where clause?
SELECT *
FROM theTable t1
WHERE CAST(t1.useridp1 AS VARCHAR) + CAST(t1.useridp2 AS VARCHAR) IN
(SELECT CAST(t2.useridp1 AS VARCHAR) + CAST(t.useridp2 AS VARCHAR)
FROM theTable t2
WHERE t2.qualified
);
This is a solution in mysql, but I believe it should transfer to sql server pretty easily. Use a subquery to pick out groups of (id1, id2) combinations with at least one True 'qualifier' row; then join that to the original table on (id1, id2).
mysql> SELECT u1.*
FROM users u1
JOIN (SELECT id1,id2
FROM users
WHERE qualifier
GROUP BY id1, id2) u2
USING(id1, id2);
+------+------+-----------+------+
| id1 | id2 | qualifier | data |
+------+------+-----------+------+
| 1 | 2 | 1 | aa |
| 1 | 2 | 0 | bb |
+------+------+-----------+------+
2 rows in set (0.00 sec)

Returning several rows from a single query, based on a value of a column

Let's say I have this table:
|Fld | Number|
1 5
2 2
And I want to make a select that retrieves as many Fld as the Number field has:
|Fld |
1
1
1
1
1
2
2
How can I achieve this? I was thinking about making a temporary table and instert data based on the Number, but I was wondering if this could be done with a single Select statement.
PS: I'm new to SQL
You can join with a numbers table:
SELECT Fld
FROM yourtable
JOIN Numbers
ON yourtable.Number <= Numbers.Number
A numbers table is just a table with a list of numbers:
Number
1
2
3
etc...
Not an great solution (since you still query your table twice, but maybe you can work from it)
SELECT t1.fld, t1.number
FROM table t1, (
SELECT ROWNUM number FROM dual
CONNECT BY LEVEL <= (SELECT MAX(number) FROM t1)) t2
WHERE t2.number<=t1.number
It generates maximum amount of rows needed and then filters it by each row.
I don't know if your RDBMS version supports it (although I rather suspect it does), but here is a recursive version:
WITH remaining (fld, times) as (SELECT fld, 1
FROM <table>
UNION ALL
SELECT a.fld, a.times + 1
FROM remaining as a
JOIN <table> as b
ON b.fld = a.fld
AND b.number > a.times)
SELECT fld
FROM remaining
ORDER BY fld
Given your source data table, it outputs this (count included for verification):
fld times
=============
1 1
1 2
1 3
1 4
1 5
2 1
2 2

SQL Group By Question

I have a table that has the below columns.
I need to find out those people that has More than 2 ApplicantRowid with same jobcategoryrowid and AssessmentTest should have atleast one row NULL with Different Appstatusrowid's.
The result should look exeactly like the below table.
Rowid ApplicantRowid JobCategoryRowid AssessmentTestRowid AppstatusRowid
10770598 6952346 157 3 5
11619676 6952346 157 NULL 6
select t.*
from
(
select ApplicantRowid, JobCategoryRowid
from tbl
group by ApplicantRowid, JobCategoryRowid
having count(AssessmentTestRowid) < count(*)
and count(distinct AppstatusRowid) > 1
) x
inner join t on t.ApplicantRowid = x.ApplicantRowid
and t.JobCategoryRowid = x.JobCategoryRowid
COUNT does not include NULLs, so count(AssessmentTestRowid) < count(*) ensures there is at least a NULL
count(distinct AppstatusRowid) > 1 ensure there are different AppstatusRowids