I have the following data:
id userid name group
1 1 A x
2 1 A y
3 1 A z
4 2 B x
5 2 B y
6 3 C y
7 4 D x
8 5 E x
9 5 E z
10 6 F x
I want to find those records that meet all this condition:
Select all rows where the a userid belongs to a group other than y but the userid also belongs to group y.
The resulting dataset will be as follows:
id userid name group
1 1 A x
3 1 A z
4 2 B x
If you see, it has resulted in two records for userid a because these are two two records belong to groups other than y but the userid 1 also belongs to group y. Same for userid 2.
I have been breaking my head on how to get this in an SQL statement but not even close to a solution.
Any help is appreciated.
Use a join:
SELECT t1.*
FROM mytable t1
INNER JOIN mytable t2
ON t1.user_id = t2.user_id AND t1.group <> t2.group AND t2.group = 'y'
I think that would be the fastest query (but please feel free to try the other solutions as well).
Add an index on user_id if not already there and maybe play with some other indexes as well (maybe a composite index on group and user_id can be utilized)
Use exists
select *
from MyTable a2
where name_group <> 'y'
and exists (select 1
from MyTable a2
where a2.name_group = 'y'
and a2.userid = a1.userid)
You can get all the users that meet the condition using aggregation and having:
select userid
from t
group by userid
having sum( group = 'y' ) > 0 and
sum( group <> 'y') > 0;
I leave it to your to put this into a query to get all the original rows.
Related
For example I have a table A and B with the following data:
A:
user_name date1 count1 count2
X 15 1 1
X 30 1 3
Y 04 1 3
B:
user_name date1 count3 count4 status
X 15 11 1 Y
X 30 13 3 N
Y 04 16 3 NA
How to join these 2 tables for each feedname with max date.
I need the output like these:
username date1 count1 count4 status
X 30 1 3 N
like these way.
Can anyone plz help in these situation.
Since according to your comment every combination (user_name, date1) exists in both tables, you can use e.g.
select a.*, b.count3, b.count4, b.status
from tableA as a
join tableB as b
on a.user_name = b.user_name and
a.date1 = b.date1
where not exists
(select 1 from tableA as a1
where a1.user_name = a.user_name
and a1.date1 > a.date1);
You want to have an index on (user_name, date1) to speed it up.
As a side note: If every entry in tableA has exactly 1 entry in tableB and vice-versa (it's not clear from your description if that is the case, but it looks like it), and thus (user_name, date1) would be a primary key in both tables, you absolutely should add the columns count3, count4 and status to tableA and get rid of tableB. You can still use the above code (without join) to find only the max entry per user.
I have a table as below,
Product Promotion exists (Y/N) Week
A Y 1
B Y 1
C Y 1
A Y 2
B Y 2
C N 2
A Y 3
B Y 3
C Y 3
A Y 4
B Y 4
C N 4
I want to see an Promition exists combination Output on total table. Something like
A, B - 4
B,C - 2
A,C - 2
Since this is Just for 3 products looks simple.. I am looking at some thousands of records, and looking for same combinations where total count of occurrence is greater than some number. If taking the above example, if that count is 4.. then my output should be
A,B - 4
Try this:
SELECT p1, p2, COUNT(*) AS cnt
FROM (
SELECT t1.Product AS p1, t2.Product AS p2
FROM mytable AS t1
JOIN mytable AS t2
ON t1.Week = t2.Week AND
t1.Product < t2.Product AND
t1.Exists = 'Y' AND t2.Exists = 'Y') AS t
GROUP BY p1, p2
ORDER BY cnt DESC
To get only pairs exceeding a certain value, just wrap the above in a subquery and add a WHERE cnt >= someValue.
Demo here
For example, in this table:
n id num
1 10 100
2 11 60
3 10 20
4 10 20
5 11 10
How do I subtract all the values of num (from top to bottom) with id = 10?
The first value of num in id=10 is subtracted to the 2nd value of num in id = 10 and the answer is subtracted to the third value of num in id = 10 (an so on and so forth if there are n numbers of num with the id =10)
It should display this:
difference of id = 10
50
Here is the working code you need:
SELECT AA.ID, (num_duo-total_sum) as num_diff FROM
(SELECT id, 2*num as num_duo, MIN(n) FROM t1 GROUP BY id ) AA LEFT JOIN
(SELECT id, SUM(num) as total_sum FROM t1 GROUP BY id) BB ON BB.id = AA.id
SQL FIDDLE
If I understand correctly, you want to take the first value for the given id and then subtract subsequent values. "first" is defined by the first column, n.
If so, then this might help:
select sum(case when t.n = f.firstn then num else - num end)
from table t cross join
(select min(n) as firstn
from table t
where id = 10
) f
where id = 10;
Here is a SQL Fiddle.
I have a table like:
ID | LABEL | SOME_VALUE
1 a rand_1
2 a NULL
3 b rand_9
4 c rand_3
5 c rand_3
6 c rand_3
7 d NULL
8 d rand_4
As you can see, ID is unique, label is not unique (can be 1 or more) and some_value is also not unique.
What I want to do is the following:
I want to get a unique list of LABELS, which exist in the database in more than one rows (min 2) and of which rows has SOME_VALUE not NULL.
So I would get:
ID | LABEL | SOME_VALUE
1 a rand_1
2 a NULL
7 d NULL
8 d rand_4
in return.
How can I achieve this?
There are two versions. First one does exactly as listed in results, eliminating rand_3 because even though it appears three times all the values are the same (I don't see distinct condition specified in question).
There must be a better way, but as they say I can't brain today, I have the dumb :-)
select *
from tbl
inner join
(
select label
FROM tbl
GROUP BY Label
HAVING count (distinct some_value)
+ sum(distinct case when some_value is null then 1 else 0 end) > 1
) a
on tbl.label = a.label
Second one retrieves C also following the requirements (some_value being not null for at least one of some_value).
select *
from tbl
inner join
(
select label
FROM tbl
GROUP BY Label
HAVING count(*) > 1 and count(some_value) > 0
) a
on tbl.label = a.label
And there is Sql Fiddle.
The HAVING parameter limits grouped items:
SELECT
Label
FROM dbo.TableName
WHERE NOT Some_Value IS NULL
GROUP BY Label
HAVING COUNT(*) > 2
SELECT t1.*
FROM yourTable t1
JOIN yourTable t2
ON t1.LABEL = t2.LABEL
AND t1.ID < t2.ID
WHERE t1.SOME_VALUE IS NOT NULL
OR t2.SOME_VALUE IS NOT NULL
This should work -
SELECT test.*
FROM (
SELECT label
FROM test
GROUP BY Label
HAVING COUNT(DISTINCT IFNULL(some_value, '~null~')) > 1
) AS tmp
INNER JOIN test
ON tmp.label = test.label;
Given the database.....
ID Name item_order Manager
1 ted 2 N
2 bob 5 N
3 tony 1 Y
4 fred 3 N
5 william 4 N
6 george 6 Y
7 cade 8 N
8 matt 7 N
I would like to be able to select managers Id prior to the current non managers name. So for example the result for bob would be tony or 3.
I can figure out how to do this with two requests
SELECT MAX( item_order) AS parent
FROM tablename WHERE item_order < 5 && Manager = 'Y'
The result from that I would make another select by the item_order. Is there a way to do this all in one select?
SELECT * FROM tablename
WHERE Manager = 'Y'
AND item_order = (SELECT MAX(item_order) AS parent
FROM tablename
WHERE item_order < 5
AND Manager = 'Y') AS t
SELECT
n.*,
ManagerName = m.Name
FROM tablename n
LEFT JOIN tablename m ON m.Manager = 'Y' AND n.item_order > m.item_order
LEFT JOIN tablename m2 ON m2.Manager = 'Y'
AND m2.item_order < n.item_order AND m2.item_order > m.Item_order
WHERE n.Manager = 'N'
AND m2.ID IS NULL
This will give you the list of all non-managers together with the names of those managers that directly precede them (based on item_order).
If you only want to return one row for a specific non-manager, add one more condition like this:
AND n.Name = 'bob'