How do I output a table that an id have different gender in their game - sql

I am not sure how to write the title of this question so the title might sound really confusing so please look at here. let suppose we have these two tables.
The first table is id, name, gender. This is the id of their game like login where name and gender is their name and gender in real life.
Where in the second table, name, and gender refer to in-game gender and name refer to in-game name as well.
id | name | gender id | name | Gender
---+------+---- ----+-------------+--------
1 | A | F 1 | a | F
2 | B | M and 1 | b | F
3 | C | M 2 | c | F
4 | D | M 3 | d | M
3 | e | M
3 | f | F
4 | g | M
4 | h | M
We want to select the id, name, and gender(in the first table), and the number of characters that an id had but that doesn't have the same gender as real-life. This might sound really confusing so here is what should be the output is
id | name | gender| #Character
---+-------+-------+-----------
2 B M 1
3 C M 3
id1: The reason it doesn't output id 1 is that id = 1 is F and she created 2 characters in the game, but both of the characters are F so she didn't 'switch' her gender so we do not print the row.
id2: We select id 2 because id = 2 is M in real-life, but he in-game character is F so we select this row.
id3: He is M in real life and one of his characters is F so we select this row
id4: He is M and none of his character is F so we don't need to print it on the screen.
Hopefully, you get what I'm trying to do here.
select id, name, gender,
(select count(*) from table_2 as t2 where t2.id = t1.id group by id) as #Character
from table_1 as t1
order by login;
Above query will print every id, name and gender and number of characters an id had, but this is not what I wanted. What should I change my code so that it works as what I Intended to do?

Actually it is simple.
We want to select the id, name, and gender(in the first table), and ... characters that an id had but that doesn't have the same gender as real-life.
select
*
from
t1
where
exists (select 1 from t2 where t1.id = t2.id and t1.gender <> t2.gender)
We want to select the id, name, and gender(in the first table), and the number of characters ...
select
*,
(select count(*) from t2 where t1.id = t2.id) as "#Character"
from
t1
where
exists (select 1 from t2 where t1.id = t2.id and t1.gender <> t2.gender)

Now that I understand the problem:
select t1.*, count(*)
from table_1 t1 join
table_2 t2
on t2.login = t1.login
group by t1.id
having count(*) filter (where t2.gender <> t1.gender) > 0;
In other words, you can filter in the having clause.
I think id and login could be confused -- your sample query does not match the sample data. But you should get the idea.

Try this:
select id,
(select count(*) from table_2 as t2 where t2.id = t1.id group by id having count(*) >1) as #Character
from table_1 as t1
order by login;

Related

query select equaled data on three columns of table with four columns and ignore one

I have table have four columns like (right ,left ,up ,down) I want to build query that show equaled data on three of the four columns;
example:
| id | right | left | up | down |
|:---|:------:|:-----:|:------:| -----:|
| 1 | street |hospital|coffee |building|
| 2 | house |hospital|coffee |building|
| 3 | road | bus |coffee |sign |
| 4 | house |hospital|coffee |sign |
| 5 | car |road |coffee |sign |
the result should be like:
id
right
left
up
down
1
street
hospital
coffee
building
2
house
hospital
coffee
building
id number 3 and 5 not included because every column should equal it's self
is that query correct
select t.* from test_table t where
(t.right,t.left,t.up) in (select t.right,t.left,t.up from test_table t group by t.right,t.left,t.up having count(*)>1)
or (t.right,t.left,t.down) in (select t.right,t.left,t.down from test_table t group by t.right,t.left,t.down having count(*)>1)
or (t.right,t.up,t.down) in (select t.right,t.up,t.down from test_table t group by t.right,t.up,t.down having count(*)>1)
or (t.left,t.up,t.down) in (select t.left,t.up,t.down from test_table t group by t.left,t.up,t.down having count(*)>1)
and t.mud_id=285 order by t.right,t.left,t.up,t.down ;
if it correct it's go in loop without result for more than 10m waiting
if not
please what is the correct query to get the result
Since there are some assumptions to be made on how how to order and/or organize the results, you may use the query below to identify each matching pair.
DECLARE #T TABLE(ID INT, [right] VARCHAR(20), [left] varchar(20), up
varchar(20), down varchar(20))
INSERT INTO #T VALUES
(1,'street','hospital','coffee','building'),
(2,'house','hospital','coffee','building'),
(3,'road','bus','coffee','sign'),
(4,'house','hospital','coffee','sign'),
(5,'car','road','coffee','sign'),
(6,'street','road','coffee','sign')
SELECT
T1.ID AS MatchID1,
T2.ID AS MatchID2
FROM
#T T1
INNER JOIN #T T2 ON T1.ID <> T2.ID
GROUP BY
T1.ID, T2.ID
HAVING
MAX(CASE WHEN T1.[right] = T2.[right] THEN 1 ELSE 0 END +
CASE WHEN T1.[left] = T2.[left] THEN 1 ELSE 0 END +
CASE WHEN T1.up = T2.up THEN 1 ELSE 0 END +
CASE WHEN T1.down = T2.down THEN 1 ELSE 0 END) = 3
MatchID1 MatchID2
2 1
1 2
4 2
2 4
6 5
5 6
A trick to bring back matches by first occurrence using:
INNER JOIN #T T2 ON T1.ID > T2.ID
MatchID1 MatchID2
1 2
2 4
5 6

How to make a comparison for the record that has rows to another rows? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have first table that has columns:
1. id
2. key
3. value
And second table(more like the list):
key
I need to get distinct id that contains all keys from second table
I have tried self join but it is very slow. Also I tried COUNT = COUNT but performance the same.
Self join:
select f.id from first
join first f2 on f.id = f2.id AND f2.key = f. key
COUNT:
select a.keyfrom #a a
where ( select SUM(CASE WHEN k.[key] is not NULL THEN 1 ELSE 0 END) from [b] b
LEFT JOIN Second s on s.key= b.[Key]
where b.[Key] = a.key) = #KeyCount
You can also check this-
SELECT A.id
FROM TAB1 A
INNER JOIN TAB2 B ON A.[key] = B.[Key]
GROUP BY A.id
HAVING COUNT(DISTINCT A.[key])
= (SELECT COUNT(DISTINCT [Key]) FROM TAB2)
This is somewhat of a stab in the dark, but perhaps this is what you're after...?
SELECT I.ID
FROM TableB B
CROSS APPLY (SELECT DISTINCT ca.ID
FROM dbo.TableA ca) I
LEFT JOIN TableA A ON B.[key] = A.[key]
AND I.ID = A.ID
GROUP BY I.ID
HAVING COUNT(CASE WHEN A.[Key] IS NULL THEN 1 END) = 0;
db<>fiddle
Assuming:
Your 2nd table lists all possible keys, and
Your first table (containing entity IDs, keys, and key values) can only contain 1 entity-key combination,
something like this may work:
SELECT [id], COUNT(*)
FROM Table1
GROUP BY [id]
HAVING COUNT(*) = (SELECT COUNT(*) FROM keys)
Now with some sample data. Assume the following keys:
+--------+----------+
| key_id | key_name |
+--------+----------+
| 1 | Key1 |
| 2 | Key2 |
| 3 | Key3 |
+--------+----------+
And the following entities:
+----+-----+-------+
| id | key | value |
+----+-----+-------+
| 1 | 1 | 1 |
| 1 | 2 | 2 |
| 1 | 3 | 3 |
| 2 | 2 | 2 |
| 2 | 3 | 3 |
+----+-----+-------+
Assume how Entity 1 has all keys, but Entity 2 is missing Key 1. So, as expected, the query returns only Entity 1.
You can use aggregation for the counting:
select f.id
from first f
where exists (select 1 from second s where s.key = f.key)
group by f.id
having count(*) = (select count(*) from second);
This assumes that there are no duplicates in the table. It also assumes that extra keys in first are ok. If not, use left join:
select f.id
from first f left join
second s
on s.key = f.key
group by f.id
having count(s.key) = (select count(*) from second) and
count(*) = count(s.key);

MS SQL Where one column is x or y and both returned

I have a table as follows with dates in. The table has many more records but simplified for asking purposes:
Name | Date | Grade
Person 1 | 01-01-2001 | B
Person 1 | 31-01-2001 | A
Person 2 | 01-01-2001 | C
Person 3 | 31-01-2001 | A
I want to return both records for Person 1 but not either of the other two. AND returns nothing obviously and OR returns everything. I want to search on the date not the grade or the person.
So the result would be:
Name | Date | Grade
Person 1 | 01-01-2001 | B
Person 1 | 31-01-2001 | A
One simple way to handle this is to aggregate by person and then assert that the two dates of interest are both present:
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT Name
FROM yourTable
WHERE Date IN ('2001-01-01', '2001-01-31')
GROUP BY Name
HAVING COUNT(DISTINCT Date) = 2
) t2
ON t1.Name = t2.Name
You can uses EXISTS to return a row if there exists another row with that name, having the other A/B grade.
select t1.*
from tablename t1
where t1.Date in ('2001-01-01', '2001-01-31')
and exists (select 1 from tablename t2
where t2.Name = t1.Name
and t2.Date in ('2001-01-01', '2001-01-31')
and t2.Date <> t1.Date)

How can I find a non duplicate value in a column, disregarding special characters?

I have an attribute field of labels relevant to my work. I am looking for duplicates within this field; the issue is, the inputs are inconsistant. For example:
Group | Label |
---------------
1 | H7 |
1 | H-7 |
2 | C9 |
2 | C 9 |
3 | D5 |
3 | M 9 |
The result I am looking for is just:
3 | D5 |
3 | M 9 |
as these are truly different from each other. I am using the following query currently:
SELECT *
FROM TABLE t3
WHERE t3.group IN (
SELECT t1.group
FROM TABLE t1, TABLE t2
WHERE t1.group = t2.group
AND (t1.label <> t2.label)
How can I get the query to disregard special characters?
If the "special" character can be anything other than alphanumeric chars, then you can use regexp_replace:
select max(t.group), max(t.label)
from your_table t
group by regexp_replace(t.label, '[^[:alnum:]]', '')
having count(*) = 1;
If there are only a limited number of special characters possible in the values, then perhaps a non-"regexp" solution would work - using replace.
Also, avoid using keywords such as "group" as identifiers.
Try:
select regexp_replace(label,'[^[:alnum:]]',''), count(1) cnt
from some_table
group by regexp_replace(label,'[^[:alnum:]]','')
having count(1) > 1
This will show the duplicate labels (based on alphanumerics only)
You can use regexp_replace():
SELECT t.*
FROM TABLE t
WHERE NOT EXISTS (SELECT 1
FROM TABLE tt
WHERE tt.group = t.group AND tt.rowid <> t.rowid AND
regexp_replace(tt.label, '[^a-zA-Z0-9]', '') = regexp_replace(t.label, '[^a-zA-Z0-9]', '')
);
This should return all the original rows that are singletons. If you want all rows for a group where all are singletons:
SELECT t.*
FROM TABLE t
WHERE t.group IN (SELECT tt.group
FROM (SELECT tt.group, regexp_replace(tt.label, '[^a-zA-Z0-9]', '') as label_clean, COUNT(*) as cnt
FROM TABLE tt
GROUP BY tt.group, regexp_replace(tt.label, '[^a-zA-Z0-9]', '')
) tt
GROUP BY tt.group
HAVING MAX(cnt) = 1
);

How to create a sql script that get distinct entry?

I have a picture as above, I would like to keep the item 2 and item 4 that have max count and name duplicated, but I need to keep the ID column. how to write the SQL script and get the result as below?
ID Name Count
2 A 5
4 B 5
Pretty sure this is what you want:
SELECT id, name, count
FROM my_table mt1
WHERE count = (SELECT MAX(count) FROM my_table mt2 WHERE mt1.name = mt2.name);
EDIT: If, however, as Chris suggests it does have duplicates:
SELECT MAX(id), name, count
FROM my_table mt1
WHERE count = (SELECT MAX(count) FROM my_table mt2 WHERE mt1.name = mt2.name)
GROUP BY name, count;
Output is:
+------+------+-------+
| id | name | count |
+------+------+-------+
| 2 | A | 5 |
| 4 | B | 5 |
+------+------+-------+
SELECT ID, Name, Count
FROM myTable
WHERE (SELECT COUNT(*) FROM myTable t2
WHERE t2.Name = myTable.Name
AND (t2.Count > myTable.Count
OR (t2.Count = myTable.Count AND t2.ID > myTable.ID))) = 0;