A query that will see which results are the most - mysql

There is a table where strings are stored by type.
How to write 1 query so that it counts and outputs the number of results of each type.
Tried to do this:
SELECT COUNT(t1.id), COUNT(t2.id)
FROM table t1
LEFT JOIN table t2
ON t2.type='n1'
WHERE t1.type='b2';
But nothing works.
There can be many types, how can this be done?

I think this is what you want:
SELECT t1.type, COUNT(DISTINCT t1.id), COUNT(DISTINCT t2.id)
FROM table1 AS t1
LEFT JOIN table2 AS t2 ON t1.type = t2.type
GROUP BY t1.type
Note that this won't show any types that are only in table2. For that you'd need a FULL OUTER JOIN, which MySQL doesn't have. See How can I do a FULL OUTER JOIN in MySQL? for how to emulate it.

Related

SQL SELECT from multiple tables or JOIN

I have two tables from which I need to get data in the same SELECT output. The thing is that I need to limit the amount of results.
Say I have an ID column that is unique in table1, but in table2 it has many rows with that ID.
Now I just want to list how many different IDs I have in table1 and some other information stored in table2.
How can I get the desired output I show in the end?
To make my idea clear I used a "messenger" database for an example.
Tables
T1
Id_thread Date
1 13Dic
2 12Dic
T2
Id_thread Message Name
1 Hi Someone
1 Hi to you Someone
2 Help me? Someother
2 Yes! Someother
Desired output
T1.Id_thread T2.Name T1.Date
1 Someone 13Dic
2 Someother 12Dic
I'd join and use distinct:
SELECT DISTINCT t1.id_thread, t2.name, t1.date
FROM t1
JOIN t2 ON t1.id_thred = t2.id_thread
Use a JOIN and GROUP BY:
SELECT t1.Id_thread, t2.Name, t1.Date
FROM t1
JOIN t2 ON t1.Id_thread = t2.Id_thread
GROUP BY t1.Id_thread
Note that if Name is the same for all rows in t2 that have the same Id_thread, that column probably should be in t1. If you fix that, you don't need the JOIN.
Try this:
SELECT DISTINCT T1.Id_thread, T2.Name, T1.Date
FROM T1
LEFT OUTER JOIN T2 ON T1.Id_thread = T2.Id_thread
select T1.Id_thread,T2.Name,T1.Date from T1
inner join T2 on T1.Id_thread = T2.Id_thread
group by T1.Id_thread
order by T1.Id_thread
You haven't specified how you want the limit the results from Table 2. Considering you just want one row, you can use a CROSS APPLY:
Select T1.Id_thread,T2Table.Name,T1.Date From T1
Cross Apply (Select Top 1 T2.Name From T2 Where T2.Id_thread=T1.Id_thread) T2Table
You can specify other conditions in the inner Select statement if you wish.

Sql queries difference

I would like to know whether this two versions are equivalent in result and which is better for performance reasons and why?
Nested Select in Select version
select
t1.c1,
t1.c2,
(select Count(t2.c1) from t2 where t2.id = t1.id) as count_t
from
t1
VS
select t1.c1,t1.c2, Count(t2.c1)
from t1,t2
where t2.id= t1.id
The first query is analog of this query -
SELECT
t1.c1,
t1.c2,
COUNT(t2.c1)
FROM t1
LEFT JOIN t2
ON t2.id = t1.id;
It selects all records from first table, and all matched records from second table (it is LEFT JOIN condition).
The second is analog of this query -
SELECT
t1.c1,
t1.c2,
COUNT(t2.c1)
FROM t1
JOIN t2
ON t2.id = t1.id;
It selects only matched records in both tables (it is INNER JOIN condition).
Well they are different queries. The top one will select all rows from t1 returning 0 for the count if there is no matching id in table t2.
The second query will only return rows where t1 and t2 both have a row with the same id.
The first query will likely suffer from performance issues on large data sets. The second query will potentially have a Cartesian issue. I would go with a join or left join based on your intent to have records from table 1 if table 2 has no related records and then add a group by statement to control the Cartesian.

Fetch the rows which have the Max value for a column - with duplicates

This answer from Bill Karwin to question 121387 worked perfectly for me..
"I see many people use subqueries or else vendor-specific features to do this, but I often do this kind of query without subqueries in the following way. It uses plain, standard SQL so it should work in any brand of RDBMS.
SELECT t1.*
FROM mytable AS t1
LEFT OUTER JOIN mytable AS t2
ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;
In other words: fetch the row from t1 where no other row exists with the same UserId and a greater Date."
However, I also need to include in the result a column from a third table (imagine another table with UserId and UserPhoneNumber columns). It feels as if it should be straightforward but it's driving me nuts. Any help would be appreciated.
Simply join the third table after the LEFT JOIN:
SELECT t1.*, t3.*
FROM mytable AS t1
LEFT OUTER JOIN mytable AS t2
ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
JOIN myothertable AS t3 ON t1.UserId = t3.UserId
WHERE t2.UserId IS NULL;

How to avoid "Ambiguous field in query" without adding Table Name or Table Alias in where clause

I have a select query in which I have joined a couple of tables say T1 and T2 and both the tables have a field named STATUS which I don't need to fetch. In the where clause I need to add WHERE STATUS=1 and some more conditions.
But somehow I just can't add the table name or table alias to the field in the where clause i.e. I can't use where T2.STATUS=1. Is there any way to always consider the STATUS=1 from the where clause being T1.STATUS so that I can avoid "Ambiguous field error"?
Here is a sample query:
select T1.name, T1.address, T1.phone, T2.title, T2.description from T1
Left Join T2 on T1.CID=T2.ID
where STATUS = 1
In above query, I want the STATUS =1 to always mean T2.STATUS
If you for some reason can't live with doing
select T1.name, T1.address, T1.phone, T2.title, T2.description from T1
Left Join T2 on T1.CID=T2.ID
where T2.STATUS = 1
Then I guess you could
SELECT T1.name, T1.address, T1.phone, T2.title, T2.description
FROM ( SELECT CID, name, address, phone
FROM T1) AS T1
LEFT JOIN T2
ON T1.CID=T2.ID
WHERE STATUS = 1
Basicly just skip getting the STATUS column from T1. Then there can be no conflict.
Bottomline; there's no simple way of doing this. The one closest to simple would be to have different names of both STATUS columns, but even that seems extreme.

SQL Server 2008 column in only one table

First a quick explanation: I am actually dealing with four tables and mining data from different places but my problem comes down to this seemingly simple concept and yes I am very new to this...
I have two tables (one and two) that both have ID columns in them. I want to query only the ID columns that are in table two only, not in both. As in..
Select ID
From dbo.one, dbo.two
Where dbo.two != dbo.one
I actually thought this would work but I'm getting odd results. Can anyone help?
SELECT t2.ID
FROM dbo.two t2
WHERE NOT EXISTS(SELECT NULL
FROM dbo.one t1
WHERE t2.ID = t1.ID)
This could also be done with a LEFT JOIN:
SELECT t2.ID
FROM dbo.two t2
LEFT JOIN dbo.one t1
ON t2.ID = t1.ID
WHERE t1.ID IS NULL
Completing the other 2 options after Joe's answer...
SELECT id
FROM dbo.two
EXCEPT
SELECT id
FROM dbo.one
SELECT t2.ID
FROM dbo.two t2
WHERE t2.ID NOT IN (SELECT t1.ID FROM dbo.one t1)
Note: LEFT JOIN will be slower than the other three, which should all give the same plan.
That's because LEFT JOIN is a join followed by a filter, the other 3 are semi-join