Getting count of distinct values - mysql

resulttable:
+-------------+-----------+
| resultSetID | projectID |
+-------------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
+-------------+-----------+
Query:
SELECT
COUNT( projectID )
FROM
resulttable
WHERE
projectID = 3
... correctly returns 2. However, I want the counts of each ID without using the WHERE condition, how do I do that?

Do you just want group by?
SELECT projectId, COUNT( * )
FROM resulttable
GROUP BY projectID;

The following query is used to get all the data for the projectId but if you want to get a specific query data without where you can use having instead
SELECT projectId, COUNT( * )
FROM resulttable
GROUP BY projectId having projectId = 3;

The following query should work for you:
SELECT projectID, SUM(resultSetID)
FROM resulttable
GROUP BY projectID;

Related

Hash the result from the database , Is it possible?

I don't know if the question wording is correct or not, but I want to do the following:
I have a table named sales It contain following columns:
------------------------------------------------
| PRODUCT_NAME | PRODUCT_QUANTITY | ExpierDate |
------------------------------------------------
if I SELECT * FROM sales then the result will be :
------------------------------------------------
| PRODUCT_NAME | PRODUCT_QUANTITY | ExpierDate |
------------------------------------------------
| TestName | 5 | 2021-6-12 |
| TestName | 2 | 2024-10-18 |
------------------------------------------------
What I need to do is to select query and get the result look like this :
------------------------------------------------
| PRODUCT_NAME | PRODUCT_QUANTITY | ExpierDate |
------------------------------------------------
| TestName | 1 | 2021-6-12 |
| TestName | 2 | 2021-6-12 |
| TestName | 3 | 2021-6-12 |
| TestName | 4 | 2021-6-12 |
| TestName | 5 | 2021-6-12 |
| TestName | 1 | 2024-10-18 |
| TestName | 2 | 2024-10-18 |
------------------------------------------------
Is this even possible ?
How can I do this..!?
I would recommend directly using a recursive CTE:
with recursive cte as (
select product_name, product_quantity, expire_date, 1 as n
from sales s
union all
select product_name, product_quantity, expire_date, n + 1
from cte
where n < product_quantity
)
select *
from cte
order by product_name, product_quantity, expire_date, n;
Here is a db<>fiddle.
As I mention in comment, with cte create pseudo data to fill up the row is really easy:
with RECURSIVE quan(quantity) AS (
SELECT 1
UNION ALL
SELECT quantity+1 FROM quan WHERE quantity < 10 --you may have to increase this
)
SELECT tb.PRODUCT_NAME ,quan.quantity as PRODUCT_QUANTITY,tb.ExpierDate
FROM [tb] -- your result table
JOIN quan on tb.PRODUCT_QUANTITY >= quan.quantity
ORDER BY tb.time,quan.quantity
here is db<>fiddle with pseudo data.
using int column as time column in pseudo data but I think query itself will still work.
In recursive cte you may have to increase the where part to create more pseudo quantity data depend on your max quantity.

how to get AVG for every record in SQL

I need to get AVG for every row in SQL for example:
this is the first table
+ ---+------+-------------+
| course_id | course_name |
+ ----------+-------------+
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | g |
+ ---+------+-------------+
This is the second table
I need to get AVG for both id 1 and 2. the result for example:
+ -------------------+------+----------+
| course_feedback_id | rate |course_id |
+ -================--+------+----------+
| 1 | 4 | 1 |
| 2 | 3 | 1 |
| 3 | 2 | 2 |
+ -------------------+------+----------+
this is the final answer that i need
+ ----------------------+
| course_id | AVG(rate) |
+ -=======--+-----------+
| 1 | 3.5 |
| 2 | 2 |
+ ----------------------+
I tried this soulution but it will give me only the first row not all records.
SELECT *, AVG(`rate`) from secondTable
please help
SELECT `id`, AVG(`rate`) FROM `your_table` GROUP BY `id`
Try this:
SELECT c.course_id, AVG(fb.rate)
FROM course AS c
INNER JOIN course_feedback AS fb ON fb.course_id = c.course_id
GROUP BY c.course_id
Select course_id,t2.rate from table1 where course_id,rate in (Select course_id,avg(rate) as rate from table group by course_id t2)
When you have multiple entries/redundant entries and you want to find some aggregation per each as in this case you got id containing redundant records, In such cases always try to use group by as group by as the name says will group records of the column to which it is applied and if you apply aggregation avg in this case will be groupwise column to which it is being applied not as a whole like for id 1 we have 2 redundant entries so itll apply avg(id1_entries)..likewise as a group.

Select two items with maximum number of common values

I have the following table:
+----+-----------+-----------+
| id | teacherId | studentId |
+----+-----------+-----------+
| 1 | 1 | 4 |
| 2 | 1 | 2 |
| 3 | 1 | 1 |
| 4 | 1 | 3 |
| 5 | 2 | 2 |
| 6 | 2 | 1 |
| 7 | 2 | 3 |
| 8 | 3 | 9 |
| 9 | 3 | 6 |
| 10 | 1 | 6 |
+----+-----------+-----------+
I need a query to find two teacherId's with maximum number of common studentId's.
In this case teachers with teacherIds 1,2 have common students with studentIds 2, 1, 3, which is greater than 1,3 having common students 6.
Thanks in Advance!
[Edit]: After several hours I've had the following solution:
SELECT * FROM (
SELECT r1tid, r2tid, COUNT(r2tid) AS cnt
FROM (
SELECT r1.teacherId AS r1tid, r2.teacherId AS r2tid
FROM table r1
INNER JOIN table r2 ON r1.studentId=r2.studentId AND r1.teacherId!=r2.teacherId
ORDER BY r1tid
) t
GROUP BY r1tid, r2tid
ORDER BY cnt DESC
) t GROUP BY cnt ORDER BY cnt DESC LIMIT 1;
I was sure that there must exist more short and elegant solution, but I could not find it.
You would do this with a self-join. Assuming no duplicates in the table:
select t.teacherid, t2.teacherid, count(*) as NumStudentsInCommon
from table t join
table t2
on t.studentid = t2.studentid and
t.teacherid < t2.teacherid
group by t.teacherid, t2.teacherid
order by NumStudentsInCommon desc
limit 1;
If you had duplicates, you would just replace count(*) with count(distinct studentid), but count(distinct) requires a bit more work.
select t.teacherId, t2.teacherId, sum(t.studentId) as NumStudentsInCommon
from table1 t join
table1 t2
on t.studentId = t2.studentId and
t.teacherId < t2.teacherId
group by t.teacherId, t2.teacherId
order by NumStudentsInCommon desc

Sql Multi-selecting one line from subgroups inside the same table

Given the following table:
id | group_s | name
_____________________
1 | 1 | pollo
2 | 1 | cordero
3 | 1 | cerdo
4 | 2 | tomates
5 | 2 | naranjas
6 | 2 | manzanas
I would like to randomly select one line from every group.
Example of possible outputs (since it is random):
id | group_s | name
_____________________
3 | 1 | cerdo
5 | 2 | naranjas
or
id | group_s | name
_____________________
1 | 1 | pollo
6 | 2 | manzanas
and so on..
I don't have a clue how to do it. I suppose I should multiselect the table.
I did try the following without success:
SELECT T2.* FROM (
SELECT group_s
FROM mytable
GROUP BY group_s ORDER BY RAND() LIMIT 1) AS T1
JOIN mytable AS T2
ON T1.group_s = T2.group_s;
Use the window function ROW_NUMBER() OVER(PARTITION BY group_s) with ORDER BY NEWID() to randomly get the ordering, something like this:
WITH CTE
AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY group_s
ORDER BY newid()) AS RN
FROM yourTable
)
SELECT id , group_s , name
FROM CTE
WHERE RN = 1;
See it in action here:
SQL Fiddle Demo

Addition of the SUM of two independant tables

i have two tables
td_sell
|----------|----------------|------------------|
| id | user_id | price |
|----------------------------------------------|
| 1 | 2 | 10 |
|----------------------------------------------|
| 2 | 1 | 5 |
|----------------------------------------------|
| 3 | 2 | 3 |
|----------------------------------------------|
and td_commsion
|----------|----------------|------------------|
| id | user_id | price |
|----------------------------------------------|
| 1 | 1 | 3 |
|----------------------------------------------|
| 2 | 1 | 5 |
|----------------------------------------------|
| 3 | 2 | 3 |
|----------------------------------------------|
now i want a sql query like this
SELECT (SUM(td_sell.price) + SUM(td_comission.price)) AS his_earning
FROM td_sell, td_comission
WHERE td_sell.user_id='1'
AND td_comission.user_id='1'
but its showing abnormal result
the result should be 13, but its showing 29
This will work:
SELECT (SELECT SUM(s.price) FROM td_sell s WHERE s.user_id = 1)
+
(SELECT SUM(c.price) FROM td_comission c WHERE c.user_id = 1)
DEMO: SqlFiddle
You are getting the sum of the Cartesian join of the two tables.
http://en.wikipedia.org/wiki/Cartesian_product
SELECT sum(price)
FROM (
SELECT * FROM td_sell
UNION ALL
SELECT * FROM td_commission
) a
where a.user_id=1
Here's a SQL Fiddle:
Fiddle
You need to do the sum separately on each table, before combining the results. Here is one way:
select (sell + commission) as his_earning
from (select SUM(td_sell.price) as sell
from td_sell
where td_sell.user_id='1'
) s cross join
(select SUM(td_comission.price) as commission
from td_comission
where td_comission.user_id='1'
) c