Select distinct from two column - php

My database like this: table name: messages
| receive | transmit |
---------------------
| 1 | 5 |
| 1 | 6 |
| 1 | 3 |
| 3 | 1 |
| 4 | 1 |
| 2 | 3 |
| 4 | 6 |
| 7 | 9 |
And i am trying to get all unique id's from each table. So my answer must be 1, 3, 4, 5, 6.
if i use SELECT DISTINCT receive FROM messages ; i will get 1, 3 ,4
if i use SELECT DISTINCT transmit FROM messages ; i will get 1, 3 ,5, 6
how do i get 1, 3, 4, 5, 6?

The default for UNION is DISTINCT:
SELECT "from" FROM tableX
UNION
SELECT "to" FROM tableX;

SELECT DISTINCT `fr_om` FROM `table`
UNION
SELECT DISTINCT `to` FROM `table` WHERE `to` NOT IN (SELECT DISTINCT `fr_om` FROM table)
Updated : you can just use UNION to remove the duplicates from your result set.
SELECT DISTINCT `fr_om` FROM `table`
UNION
SELECT DISTINCT `to` FROM `table`

Related

Stuck in building MySQL query

Given an example of table:
id | item_id | user_id | bid_price
----------------------------------
The task is to select rows with minimum bid_price for each item_id in the provided set.
For example: item_id = [1, 2, 3] - so I need to select up to three (3) rows, having a minimum bid_price.
Example of data:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
2 | 1 | 12 | 2
3 | 1 | 13 | 3
4 | 1 | 14 | 1
5 | 1 | 15 | 4
6 | 2 | 16 | 2
7 | 2 | 17 | 1
8 | 3 | 18 | 2
9 | 3 | 19 | 3
10 | 3 | 18 | 2
Expected result:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
7 | 2 | 17 | 1
8 | 3 | 18 | 2
Actually, I'm using Symfony/Docine DQL, but it will be enough with a plain SQL example.
For the all the columns in the rows you could use a inner join on subselect for min bid price
select m.id, m.item_id, m.user_id, m.bid_price
from my_table m
inner join (
select item_id, min(id) min_id, min(bid_price) min_price
from my_table
where item_id IN (1,2,3)
group by item_id
) t on t.item_id = m.item_id
and t.min_price= m.bid_price
and t.min_id = m.id
or .. if you have some float data type you could use a acst for unsigned
select m.id, m.item_id, m.user_id, cast(m.bid_price as UNSIGNED)
from my_table m
inner join (
select item_id, min(id) min_id, min(bid_price) min_price
from my_table
where item_id IN (1,2,3)
group by item_id
) t on t.item_id = m.item_id
and t.min_price= m.bid_price
and t.min_id = m.id
You can use MIN() with GROUP BY in the query:
SELECT id, item_id, MIN(bid_price) AS min_bid, user_id
FROM your_tbl
GROUP BY item_id
HAVING item_id in(1, 2, 3);
Use this query:
SELECT id, item_id, user_id, min(bid_price) as bid_price
FROM YOUR_TABLE_NAME
GROUP BY item_id;

mysql count how many times the same value appears across multiple colums

during a group project we recent sent out a survey regarding the site we're building. I've put the data into a mysql database and i'm trying to figure out how to count how many times certain scores was given in each category
the table looks like this
+-----------------+--------------+-------------------+
| Design | Ease of use | Responsiveness |
+-----------------+--------------+-------------------+
| 5 | 5 | 5
| 4 | 4 | 4
| 3 | 3 | 3
| 2 | 2 | 2
| 1 | 1 | 1
| 5 | 4 | 2
| 5 | 4 | 4
| 3 | 3 | 3
| 1 | 2 | 2
| 1 | 2 | 2
I've found a query that works for one colum
SELECT Design, COUNT(*) AS num FROM table GROUP BY Design
I would then get
Design | num
-------------
5 | 3
4 | 1
3 | 2
2 | 1
1 | 3
If i were to try
SELECT Design, COUNT(*) AS num1, Ease of use, COUNT(*) as num2 FROM table
GROUP BY Design, Ease of use
The table gets totally messed up.
What I want is to get
Design | num1 | Ease of use | num2 | Responsiveness | num3
------------- --------------------------------------------------
5 | 3 | 5 | 1 | 5 | 1
4 | 1 | 4 | 3 | 4 | 2
3 | 2 | 3 | 2 | 3 | 2
2 | 1 | 2 | 3 | 2 | 4
1 | 3 | 1 | 1 | 1 | 1
Any help would be greatly appreciated
You can unpivot the values and then aggregate. In MySQL, that typically uses union all:
select val, count(*)
from ((select design as val from table) union all
(select ease_of_use from table) union all
(select responsiveness from table
) der
group by val
order by val desc;
For what you want to get, you can do:
select val, sum(design) as design, sum(ease_of_use) as ease_of_use,
sum(responsiveness) as responsiveness
from ((select design as val, 1 as design, 0 as ease_of_use, 0 as responsiveness from table) union all
(select ease_of_use, 0, 1, 0 from table) union all
(select responsiveness, 0, 0, 1 from table
) der
group by val
order by val desc;
I see no reason to repeat the value three times.
Use a synthesized table with the different values, and join this with subqueries that get the counts of each score.
SELECT nums.num AS Design, t1.count AS num1,
nums.num AS `Ease of Use`, t2.count AS num2,
nums.num AS Responsiveness, t3.count AS num3
FROM (SELECT 1 AS num UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) AS nums
LEFT JOIN (
SELECT Design, COUNT(*) AS count
FROM yourTable
GROUP BY Design) AS t1 ON t1.Design = nums.num
LEFT JOIN (
SELECT `Ease of Use`, COUNT(*) AS count
FROM yourTable
GROUP BY `Ease of Use`) AS t2 ON t2.`Ease of Use` = nums.num
LEFT JOIN (
SELECT Responsiveness, COUNT(*) AS count
FROM yourTable
GROUP BY Responsiveness) AS t3 ON t3.Responsiveness = nums.num
DEMO
Here are three ways:
select s.score,
(select count(*) from tbl where `Design` = s.score) as `Design`,
(select count(*) from tbl where `Ease of use` = s.score) as `Ease of use`,
(select count(*) from tbl where `Responsiveness` = s.score) as `Responsiveness`
from (
select Design as score from tbl
union select `Ease of use` from tbl
union select Responsiveness from tbl
) s
order by score desc
http://sqlfiddle.com/#!9/002303/2
select s.score,
(select count(*) from tbl where `Design` = s.score) as `Design`,
(select count(*) from tbl where `Ease of use` = s.score) as `Ease of use`,
(select count(*) from tbl where `Responsiveness` = s.score) as `Responsiveness`
from (select 1 as score union select 2 union select 3 union select 4 union select 5) s
order by score desc
http://sqlfiddle.com/#!9/002303/4
select s.score,
sum(`Design` = score) as `Design`,
sum(`Ease of use` = score) as `Ease of use`,
sum(`Responsiveness` = score) as `Responsiveness`
from (select 1 as score union select 2 union select 3 union select 4 union select 5) s
cross join tbl t
group by s.score
order by s.score desc
http://sqlfiddle.com/#!9/002303/5
They all return the same result:
| score | Design | Ease of use | Responsiveness |
|-------|--------|-------------|----------------|
| 5 | 3 | 1 | 1 |
| 4 | 1 | 3 | 2 |
| 3 | 2 | 2 | 2 |
| 2 | 1 | 3 | 4 |
| 1 | 3 | 1 | 1 |
As #futureweb wrote in the comment, I don't see a reason to repeat the score three times. Though you can if you want using aliases.
If you have millions of rows ;-) and no indexes you would want to get the result with only one table scan. This is possible with:
select
sum(`Design` = 1) as d1,
sum(`Design` = 2) as d2,
sum(`Design` = 3) as d3,
sum(`Design` = 4) as d4,
sum(`Design` = 5) as d5,
sum(`Ease of use` = 1) as e1,
sum(`Ease of use` = 2) as e2,
sum(`Ease of use` = 3) as e3,
sum(`Ease of use` = 4) as e4,
sum(`Ease of use` = 5) as e5,
sum(`Responsiveness` = 1) as r1,
sum(`Responsiveness` = 2) as r2,
sum(`Responsiveness` = 3) as r3,
sum(`Responsiveness` = 4) as r4,
sum(`Responsiveness` = 5) as r5
from tbl
This will return the data you need, but not in the form you'd like:
| d1 | d2 | d3 | d4 | d5 | e1 | e2 | e3 | e4 | e5 | r1 | r2 | r3 | r4 | r5 |
|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|
| 3 | 1 | 2 | 1 | 3 | 1 | 3 | 2 | 3 | 1 | 1 | 4 | 2 | 2 | 1 |
So you would need to post process it.

How to do a select statement to claim relationship exist? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
External subject group
| pk | group_id | subid |
|----|----------|-------|
| 1 | 1 | s1 |
| 2 | 1 | s2 |
| 3 | 1 | s3 |
| 4 | 2 | x1 |
| 5 | 2 | x2 |
| 6 | 3 | y1 |
| 7 | 3 | y2 |
| 8 | 3 | y3 |
Internal subject group
| pk | group_id | subid |
|----|----------|-------|
| 1 | 1 | a1 |
| 2 | 1 | a2 |
| 3 | 1 | a3 |
| 4 | 2 | b1 |
| 5 | 3 | c1 |
| 5 | 3 | c2 |
| 7 | 3 | c3 |
| 8 | 3 | b4 |
I am using php and sql (oracle) at the moment. For example,
I have array of external subjects:
[s1, s2, s3]
I have array of internal subjects
[a1, a2, a3]
My attempt is that (incorrectly)
SELECT
group_id
FROM
external_subject_group e_s_g,
internal_subject_group i_s_g
WHERE
e_s_g.group_id = i_s_g.group_id AND
e_s_g.subid = "s1" AND
e_s_g.subid = "s2" AND
e_s_g.subid = "s3" AND
i_s_g.subid = "a1" AND
i_s_g.subid = "b1" AND
i_s_g.subid = "c1"
The group id either exist or empty.
Basically, I try to wrap this sql query into a php function. If the query returns the relationship id. I know the relationship [s1, s2, s3] x [a1, a2, a3] exist.
for example, another relationship is [x1, x2] x [b1].
I suspect you want more than just a simple where condition, and that you are looking for a way to identify a group that has all 3 values. Here are a couple of alternative queries. The first is my best guess, the second is just for comparison and you can trial these examples at SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE Table1
(PK int, GROUP_ID int, SUBID varchar2(20))
;
INSERT ALL
INTO Table1 (PK, GROUP_ID, SUBID)
VALUES (1, 1, 's1')
INTO Table1 (PK, GROUP_ID, SUBID)
VALUES (2, 1, 's2')
INTO Table1 (PK, GROUP_ID, SUBID)
VALUES (3, 1, 's3')
INTO Table1 (PK, GROUP_ID, SUBID)
VALUES (4, 2, 'x1')
INTO Table1 (PK, GROUP_ID, SUBID)
VALUES (5, 2, 'x2')
INTO Table1 (PK, GROUP_ID, SUBID)
VALUES (6, 3, 'y1')
INTO Table1 (PK, GROUP_ID, SUBID)
VALUES (7, 3, 'y2')
INTO Table1 (PK, GROUP_ID, SUBID)
VALUES (8, 3, 'y3')
SELECT * FROM dual
;
The following query uses GROUP BY and HAVING SUM(...) as a constct to require that ALL 3 wanted subid's MUST be used.
Query 1:
select group_id
from Table1
group by group_id
having SUM(case when subid in('s1','s2','s3') then 1 else 0 end) = 3
Result:
| GROUP_ID |
|----------|
| 1 |
Query 2:
This query only requires that ANY ONE of the subids listed have been used.
select distinct group_id
from Table1
where subid in('s1','s2','s3')
Result:
| GROUP_ID |
|----------|
| 1 |
+EDIT
You might also need to use UNION ALL
select group_id
from (
select pk,group_id,subid from external_subject_group e_s_g
UNION ALL
select pk,group_id,subid from internal_subject_group i_s_g
) t1
group by group_id
having SUM(case when subid in('s1','s2','s3','a1','a2','a3') then 1 else 0 end) = 6

mysql - split columns to rows dynamically

I have the table training, I want to split Training_name Column values to multiple Rows:
SLNO Category Training_name
1 A 1,5,9,15,12,16
2 B 2,6,10,17
3 C 1,3,7,19,14,18
I used below Query but using this Query i can only split into two rows...
SELECT training.SLNO,training.CATEGORY, SubString_Index(training.TRAINING_NAME, ',', 1) AS TRAINING_NAME FROM training UNION ALL SELECT training.SLNO,training.CATEGORY, SubString_Index(training.TRAINING_NAME, ',', -1) FROM training
i am trying to get the table as given below,Please help me out
SLNO Category Training_name
1 A 1
1 A 5
1 A 9
1 A 15
1 A 12
1 A 16
2 B 2
2 B 6
2 B 10
2 B 17
3 C 1
3 C 3
3 C 7
3 C 19
3 C 14
3 C 18
DROP TABLE IF EXISTS my_bad_table;
DROP TABLE IF EXISTS my_good_table;
CREATE TABLE my_bad_table
(SLNO INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,Category CHAR(1) NOT NULL
,Training_name VARCHAR(200) NOT NULL
);
INSERT INTO my_bad_table VALUES
(1,'A','1,5,9,15,12,16'),
(2,'B','2,6,10,17'),
(3,'C','1,3,7,19,14,18');
CREATE TABLE my_good_table AS
SELECT DISTINCT x.SLNO
, x.Category
, CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(x.training_name,',',y.i+1),',',-1) AS UNSIGNED) training_name
FROM my_bad_table x
, (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5
UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 8 UNION SELECT 9) y
ORDER
BY slno
, category
, training_name;
SELECT * FROM my_good_table;
+------+----------+---------------+
| SLNO | Category | training_name |
+------+----------+---------------+
| 1 | A | 1 |
| 1 | A | 5 |
| 1 | A | 9 |
| 1 | A | 12 |
| 1 | A | 15 |
| 1 | A | 16 |
| 2 | B | 2 |
| 2 | B | 6 |
| 2 | B | 10 |
| 2 | B | 17 |
| 3 | C | 1 |
| 3 | C | 3 |
| 3 | C | 7 |
| 3 | C | 14 |
| 3 | C | 18 |
| 3 | C | 19 |
+------+----------+---------------+
If 1s are always 'A', etc, then a further step towards normalization is required to remove that redundancy.
Here is one method:
select slno, category, substring_index(training_name, ',', 1) + 0 as training_id
from t
union all
select slno, category, substring_index(substring_index(training_name, ',', 2), ',', -1) + 0 as training_id
from t
where training_name like '%,%'
union all
select slno, category, substring_index(substring_index(training_name, ',', 3), ',', -1) + 0 as training_id
from t
where training_name like concat('%', repeat(',%', 2))
union all
select slno, category, substring_index(substring_index(training_name, ',', 4), ',', -1) + 0 as training_id
from t
where training_name like concat('%', repeat(',%', 3))
union all
. . .
Repeat for as often as you need. Store the results in a new table. Fix foreign key references and other aspects of the data. Drop the original table (well, archive it) and never use that structure again.
It works to me..
SELECT DISTINCT x.PARENT_SLNO, x.TRAINING_CATEGORY, CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(x.TRAINING_NAME,',',y.i+1),',',-1) AS UNSIGNED) TRAINING_NAME FROM assessment_training x, (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 8 UNION SELECT 9) y where PARENT_SLNO = 3 and TRAINING_CATEGORY='technical' ORDER BY PARENT_SLNO,TRAINING_CATEGORY,TRAINING_NAME

join 2 table with SUM and Group By

i have 2 table one is buy_table and another is sale_table. in this query in this query i will have to use SUM , group by and date also but i am not able to understand and its showing som error
//buy table
----------------------------------------------------------
| id | product_id | quantity | total_price | date |
----------------------------------------------------------
| 1 | 1 | 5 | 500 | 2014-12-05 |
----------------------------------------------------------
| 2 | 2 | 5 | 500 | 2014-12-15 |
----------------------------------------------------------
| 3 | 1 | 5 | 500 | 2014-12-01 |
//Sale_table
----------------------------------------------------------
| id | product_id | quantity | total_price | date |
----------------------------------------------------------
| 1 | 1 | 5 | 1800 | 2014-12-05 |
----------------------------------------------------------
| 2 | 2 | 5 | 500 | 2014-12-15 |
----------------------------------------------------------
| 3 | 3 | 5 | 500 | 2015-01-01 |
----------------------------------------------------------
| 4 | 3 | 5 | 500 | 2015-01-01 |
i need like this.
----------------------------------------------------------------------
| id | product_id |buy_quantity| buy_total | sale_quantity|sale_total
----------------------------------------------------------------------
| 1 | 1 | 10 | 1000 | 5 | 1800
----------------------------------------------------------------------
| 2 | 2 | 5 | 500 | 5 | 500
----------------------------------------------------------------------
| 3 | 3 | 5 | 500 | 10 | 1000
----------------------------------------------------------------------
SELECT
A.ID,A.PRODUCT_ID,A.BUY_QUANTITY,B.SALE_QUANTITY,A.BUY_TOTAL,B.SALE_TOTAL,A.DATE
(select id,product_id,sum(quantity) as buy_quantity,sum(total_price) as
buy_total,date from buy_table group by product_id) A INNER JOIN (SELECT sum
(quantity) as SALE_quantity,sum(total_price) as SALE_total FROM SALE_TABLE group by product_id) B
ON A.PRODUCT_ID=B.PRODUCT_ID
I will suppose that you mistyped the third row in buy table and you meant to type 3 in product_id and the id column in the desired result set is just a serial which is not relevant to any data. The below query might be the answer for your inquiry:
-- Simluating your tables
DECLARE #buyTable AS TABLE (id INT, product_id INT, quantity INT, total_price INT, date DATE)
DECLARE #saleTable AS TABLE (id INT, product_id INT, quantity INT, total_price INT, date DATE)
INSERT INTO #buyTable
VALUES(1, 1, 5, 500, '2014-12-05'), (2, 2, 5, 500, '2014-12-15'), (3, 3, 5, 500, '2014-12-01')
INSERT INTO #saleTable
VALUES(1, 1, 5, 1800, '2014-12-05'), (2, 2, 5, 500, '2014-12-15'), (3, 3, 5, 500, '2014-01-01'), (4, 3, 5, 500, '2015-01-01')
-- Simluation stops here
SELECT ROW_NUMBER() OVER(ORDER BY b.product_id) AS id, b.product_id, buy_quantity, buy_total, sale_quantity, sale_total FROM
(
SELECT product_id, SUM(quantity) AS buy_quantity, SUM(total_price) AS buy_total FROM #buyTable
GROUP BY product_id
) b
INNER JOIN
(
SELECT product_id, SUM(quantity) AS sale_quantity, SUM(total_price) AS sale_total FROM #saleTable
GROUP BY product_id
) s ON s.product_id = b.product_id
The id column in your results doesn't make sense if you want to show buy/sale by product.
To ensure you always get all the products, you need to use your product table as the driving table (Assuming you have a product table)
select
p.product_id,
(SELECT SUM(b.quantity) FROM buy b WHERE b.product_id = p.product_id) as buy_quantity,
(SELECT SUM(b.total_price) FROM buy b WHERE b.product_id = p.product_id) as buy_total,
(SELECT SUM(s.quantity) FROM sale s WHERE s.product_id = p.product_id) as sale_quantity,
(SELECT SUM(s.total_price) FROM sale s WHERE s.product_id = p.product_id) as sale_total
from product p

Categories