How can I select posts that have more than specific votes? - mysql

My tables structure:
// posts
+----+----------------------------------------+-----------+
| Id | body | user_id |
+----+----------------------------------------+-----------+
| 1 | content1 | 2 |
| 2 | content2 | 9 |
| 3 | content3 | 6 |
| 4 | content4 | 4 |
| 5 | content5 | 2 |
| 6 | content6 | 8 |
| 7 | content7 | 4 |
| 8 | content8 | 2 |
+----+----------------------------------------+-----------+
// votes
+----+---------+-------+
| id | post_id | value |
+----+---------+-------+
| 1 | 2 | 1 |
| 2 | 3 | -1 |
| 3 | 2 | 1 |
| 4 | 8 | -1 |
| 5 | 1 | 1 |
| 6 | 8 | 1 |
| 7 | 2 | -1 |
| 8 | 8 | -1 |
| 9 | 2 | 1 |
+----+---------+-------+
I need to select posts that have more than 1 vote total score. So this is expected output:
+----+----------------------------------------+-----------+-------------+
| Id | body | user_id | total_votes |
+----+----------------------------------------+-----------+-------------+
| 2 | content2 | 9 | 2 |
+----+----------------------------------------+-----------+-------------+
How can I do that?

create table qanda
( id int not null,
body varchar(100) not null,
user_id int not null
);
insert qanda values
(1,'a',2),
(2,'a',9),
(3,'a',6),
(4,'a',4),
(5,'a',2),
(6,'a',8),
(7,'a',2),
(8,'a',2);
create table votes
( id int not null,
post_id int not null,
value int not null
);
insert votes values
(1,2,1),
(2,3,-1),
(3,2,1),
(4,8,-1),
(5,1,1),
(6,8,1),
(7,2,-1),
(8,8,-1),
(9,2,1);
Query
select q.id,q.body,q.user_id,sum(v.value) as votes
from qanda q
join votes v
on v.post_id=q.id
group by q.id,q.body,q.user_id
having votes>1;
+----+------+---------+-------+
| id | body | user_id | votes |
+----+------+---------+-------+
| 2 | a | 9 | 2 |
+----+------+---------+-------+

Related

Multiple Selects on Insert Statement - mySQL

I have 2 tables.
1.
**code**
id
name
2.
**code_category**
id
code_id
category_id
discount
I have a list of 15000 codes in the database without the code_category yet. I only have 1 sample one to reference in code_category. I have to mass add in the code_category with 20 categories per code.
I am thinking of left joining both tables to get where code_id is null that gets me all the un-attached codes but I need another select statement to get the 20 different types of code_category rows to enter per code.
insert into code_category (code_id, category_id, discount)
values
(select id from code c
left join code_category cc on cc.code_id = c.id
where cc.code_id is null)
union
(select categoryid, discount from code_category where c.id = 123)
123 being the reference id.
I built a simplified example of your tables in a SQL Fiddle, then ran just the select (shown below) to see what rows would be inserted. See if this example answers your question.
Note how in the select I left join twice, once to get a list of categories, and again to find the missing ones.
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE IF NOT EXISTS `code` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
ENGINE=MyISAM
AUTO_INCREMENT=1
DEFAULT CHARSET=utf8
COLLATE=utf8_unicode_ci
COMMENT '';
CREATE TABLE IF NOT EXISTS `code_category` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`codeid` INT(11) UNSIGNED NULL DEFAULT NULL,
`categoryid` INT(11) UNSIGNED NULL DEFAULT NULL,
`discount` INT(11) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_codecategory_catid` (`categoryid`),
KEY `idx_codecategory_codeid` (`codeid`)
)
ENGINE=MyISAM
AUTO_INCREMENT=1
DEFAULT CHARSET=utf8
COLLATE=utf8_unicode_ci
COMMENT '';
INSERT INTO `code`
(`id`,`name`)
VALUES
(1,'code1'),
(2,'code2'),
(3,'code3'),
(4,'code4');
INSERT INTO `code_category`
(`codeid`,`categoryid`,`discount`)
VALUES
(1,1,3),
(2,1,2),
(1,2,2),
(1,3,3),
(1,4,2),
(1,5,2),
(1,6,2),
(1,7,2),
(1,8,2),
(1,9,2),
(1,10,2),
(1,11,2),
(1,12,2),
(1,13,2),
(1,14,2),
(1,15,2),
(1,16,2),
(1,17,2),
(1,18,2),
(1,19,2),
(1,20,2);
Query 1:
SELECT
c.id,
cc1.codeid,
cc1.categoryid,
cc1.discount
FROM code c
LEFT JOIN code_category cc1
ON cc1.codeid = 1
LEFT JOIN code_category cc
ON cc.codeid = c.id AND cc.codeid = cc1.codeid
WHERE cc.codeid is null
ORDER BY c.id,cc1.codeid,cc1.categoryid
Results:
| id | codeid | categoryid | discount |
|----|--------|------------|----------|
| 2 | 1 | 1 | 3 |
| 2 | 1 | 2 | 2 |
| 2 | 1 | 3 | 3 |
| 2 | 1 | 4 | 2 |
| 2 | 1 | 5 | 2 |
| 2 | 1 | 6 | 2 |
| 2 | 1 | 7 | 2 |
| 2 | 1 | 8 | 2 |
| 2 | 1 | 9 | 2 |
| 2 | 1 | 10 | 2 |
| 2 | 1 | 11 | 2 |
| 2 | 1 | 12 | 2 |
| 2 | 1 | 13 | 2 |
| 2 | 1 | 14 | 2 |
| 2 | 1 | 15 | 2 |
| 2 | 1 | 16 | 2 |
| 2 | 1 | 17 | 2 |
| 2 | 1 | 18 | 2 |
| 2 | 1 | 19 | 2 |
| 2 | 1 | 20 | 2 |
| 3 | 1 | 1 | 3 |
| 3 | 1 | 2 | 2 |
| 3 | 1 | 3 | 3 |
| 3 | 1 | 4 | 2 |
| 3 | 1 | 5 | 2 |
| 3 | 1 | 6 | 2 |
| 3 | 1 | 7 | 2 |
| 3 | 1 | 8 | 2 |
| 3 | 1 | 9 | 2 |
| 3 | 1 | 10 | 2 |
| 3 | 1 | 11 | 2 |
| 3 | 1 | 12 | 2 |
| 3 | 1 | 13 | 2 |
| 3 | 1 | 14 | 2 |
| 3 | 1 | 15 | 2 |
| 3 | 1 | 16 | 2 |
| 3 | 1 | 17 | 2 |
| 3 | 1 | 18 | 2 |
| 3 | 1 | 19 | 2 |
| 3 | 1 | 20 | 2 |
| 4 | 1 | 1 | 3 |
| 4 | 1 | 2 | 2 |
| 4 | 1 | 3 | 3 |
| 4 | 1 | 4 | 2 |
| 4 | 1 | 5 | 2 |
| 4 | 1 | 6 | 2 |
| 4 | 1 | 7 | 2 |
| 4 | 1 | 8 | 2 |
| 4 | 1 | 9 | 2 |
| 4 | 1 | 10 | 2 |
| 4 | 1 | 11 | 2 |
| 4 | 1 | 12 | 2 |
| 4 | 1 | 13 | 2 |
| 4 | 1 | 14 | 2 |
| 4 | 1 | 15 | 2 |
| 4 | 1 | 16 | 2 |
| 4 | 1 | 17 | 2 |
| 4 | 1 | 18 | 2 |
| 4 | 1 | 19 | 2 |
| 4 | 1 | 20 | 2 |
|----|--------|------------|----------|
You may need to change the column names to match your tables.

Select Same Column From 2 Tables into 1 Column in View

I have two column with the same name in different tables.
I want to join them into one column in a view.
Here my first table stocks:
+----------+------------+------------+---------+----------------+--------+
| stock_id | stock_cost | stock_left | item_id | purchasedtl_id | trx_id |
+----------+------------+------------+---------+----------------+--------+
| 1 | 1000 | 0 | 1 | 1 | 1 |
| 2 | 1000 | 5 | 1 | 2 | 2 |
| 3 | 1000 | 1 | 1 | 3 | 4 |
+----------+------------+------------+---------+----------------+--------+
Second table stocks_out
+-------------+----------------+--------------+---------+----------+------------+--------+
| stockout_id | stockout_price | stockout_qty | item_id | stock_id | saledtl_id | trx_id |
+-------------+----------------+--------------+---------+----------+------------+--------+
| 1 | 2000 | 1 | 1 | 1 | 1 | 3 |
+-------------+----------------+--------------+---------+----------+------------+--------+
And I want to join them to be like this trx_id, trx_no, trx_closetime, trx_type stock_id, stock_cost, stockout_id, stock_out_cost, stockout_price, item_id
item_id is the field I want to join in one column.
The current Query is :
select `transactions`.`trx_id` AS `trx_id`,`transactions`.`trx_no` AS `trx_no`,`transactions`.`trx_closetime` AS `trx_closetime`,`transactions`.`trx_type` AS `trx_type`,`stocks`.`stock_id` AS `stock_id`,`stocks`.`stock_cost` AS `stock_cost`,`stock_out`.`stockout_id` AS `stockout_id`,`stock_out`.`stockout_price` AS `stockout_price` from ((`transactions` left join `stocks` on(`stocks`.`trx_id` = `transactions`.`trx_id`)) left join `stock_out` on(`stock_out`.`trx_id` = `transactions`.`trx_id`)) order by `transactions`.`trx_closetime`;
And the current result:
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
| trx_id | trx_no | trx_closetime | trx_type | stock_id | stock_cost | stockout_id | stockout_price |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
| 1 | 02002-02-170415-001 | 2017-04-15 19:40:03 | 2 | 1 | 1000 | NULL | NULL |
| 2 | 02002-02-170415-002 | 2017-04-15 19:40:13 | 2 | 2 | 1000 | NULL | NULL |
| 3 | 02002-01-170415-001 | 2017-04-15 19:40:57 | 1 | NULL | NULL | 1 | 2000 |
| 4 | 02002-02-170415-003 | 2017-04-15 19:41:14 | 2 | 3 | 1000 | NULL | NULL |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
Found it guys.
I just need to add the following query as the column
COALESCE(`stocks`.`item_id`, `stocks_out`.`item_id`) AS `item_id`
So the query will be like
select `transactions`.`trx_id` AS `trx_id`,`transactions`.`trx_no` AS `trx_no`,`transactions`.`trx_closetime` AS `trx_closetime`,`transactions`.`trx_type` AS `trx_type`,`stocks`.`stock_id` AS `stock_id`,`stocks`.`stock_cost` AS `stock_cost`,`stock_out`.`stockout_id` AS `stockout_id`,`stock_out`.`stockout_price` AS `stockout_price`, COALESCE(`stocks`.`item_id`, `stocks_out`.`item_id`) AS `item_id from ((`transactions` left join `stocks` on(`stocks`.`trx_id` = `transactions`.`trx_id`)) left join `stock_out` on(`stock_out`.`trx_id` = `transactions`.`trx_id`)) order by `transactions`.`trx_closetime`;
And the result:
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+
| trx_id | trx_no | trx_closetime | trx_type | stock_id | stock_cost | stockout_id | stockout_price | item_id |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+
| 1 | 02002-02-170415-001 | 2017-04-15 19:40:03 | 2 | 1 | 1000 | NULL | NULL | 1 |
| 2 | 02002-02-170415-002 | 2017-04-15 19:40:13 | 2 | 2 | 1000 | NULL | NULL | 1 |
| 3 | 02002-01-170415-001 | 2017-04-15 19:40:57 | 1 | NULL | NULL | 1 | 2000 | 1 |
| 4 | 02002-02-170415-003 | 2017-04-15 19:41:14 | 2 | 3 | 1000 | NULL | NULL | 1 |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+

How can I update two different tables in one query?

I have two tables like this:
// users
+----+--------+----------------------------+------------------+
| id | name | email | notification_num |
+----+--------+----------------------------+------------------+
| 1 | John | John134#gmail.com | 4 |
| 2 | Peter | matrix_peter#ymail.com | 2 |
| 3 | Jack | jk_43m#gmail.com | 6 |
+----+--------+----------------------------+------------------+
// notifications
+----+---------+---------+------+
| id | post_id | user_id | seen |
+----+---------+---------+------+
| 1 | 4325 | 2 | NULL |
| 2 | 8765 | 3 | NULL |
| 3 | 5454 | 3 | 1 |
| 4 | 4346 | 2 | NULL |
| 5 | 3243 | 1 | 1 |
| 6 | 3246 | 2 | 1 |
| 7 | 3764 | 3 | 1 |
+----+---------+---------+------+
Ok, All I have is just a user_id. For example :user_id = 2, And then I want this output:
// users
+----+--------+----------------------------+------------------+
| id | name | email | notification_num |
+----+--------+----------------------------+------------------+
| 1 | John | John134#gmail.com | 4 |
| 2 | Peter | matrix_peter#ymail.com | 0 |
| 3 | Jack | jk_43m#gmail.com | 6 |
+----+--------+----------------------------+------------------+
// notifications
+----+---------+---------+------+
| id | post_id | user_id | seen |
+----+---------+---------+------+
| 1 | 4325 | 2 | 1 |
| 2 | 8765 | 3 | NULL |
| 3 | 5454 | 3 | 1 |
| 4 | 4346 | 2 | 1 |
| 5 | 3243 | 1 | 1 |
| 6 | 3246 | 2 | 1 |
| 7 | 3764 | 3 | 1 |
+----+---------+---------+------+
As you see, I want to update users.cotification_num and set it to 0 (for such an user), and I also want to update notifications.seen and set all rows to 1 (for such an user). How can I do that?
I can do that by two different queries like this:
UPDATE users SET notification_num = 0 WHERE id = :user_id
UPDATE notifications SET seen = 1 WHERE seen is NULL and user_id = :user_id
But I want to know how can I do that by one query?
You can use a multiple-table UPDATE:
UPDATE users u LEFT JOIN notifications n ON n.user_id = u.id
SET u.notification_num = 0,
n.seen = 1
WHERE u.id = 2
You can join the tables together to UPDATE both in a single query:
UPDATE users, notifications
SET users.notification_num = 0
, notification.seen = 1
WHERE users.id = notifications.user_id AND
users.id = 2 AND
notifications.seen is NULL
Read here for more information. Another option would be to simply do 2 separate updates within a transaction:
START TRANSACTION;
UPDATE users SET notification_num = 0 WHERE id = 2;
UPDATE notifications SET seen = 1 WHERE user_id = 2 AND notifications.seen is NULL;
COMMIT;
Note that my schema is very slightly different from yours - but it makes very little difference...
DROP TABLE IF EXISTS users;
CREATE TABLE users
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(12) NOT NULL
,email VARCHAR(20) NOT NULL
,notification_num INT NOT NULL
);
INSERT INTO users VALUES
(1,'John','John134#gmail.com',4),
(2,'Peter','matrix_peter#ymail.com',2),
(3,'Jack','jk_43m#gmail.com',6);
DROP TABLE IF EXISTS notifications;
CREATE TABLE notifications
(post_id INT NOT NULL
,user_id INT NOT NULL
,seen TINYINT DEFAULT 0
,PRIMARY KEY(post_id,user_id)
);
INSERT INTO notifications VALUES
(4325,2,0),
(8765,3,0),
(5454,3,1),
(4346,2,0),
(3243,1,1),
(3246,2,1),
(3764,3,1);
SELECT * FROM notifications;
+---------+---------+------+
| post_id | user_id | seen |
+---------+---------+------+
| 3243 | 1 | 1 |
| 3246 | 2 | 1 |
| 3764 | 3 | 1 |
| 4325 | 2 | 0 |
| 4346 | 2 | 0 |
| 5454 | 3 | 1 |
| 8765 | 3 | 0 |
+---------+---------+------+
SELECT * FROM users;
+----+-------+----------------------+------------------+
| id | name | email | notification_num |
+----+-------+----------------------+------------------+
| 1 | John | John134#gmail.com | 4 |
| 2 | Peter | matrix_peter#ymail.c | 2 |
| 3 | Jack | jk_43m#gmail.com | 6 |
+----+-------+----------------------+------------------+
UPDATE users u
JOIN notifications n
ON n.user_id = u.id
SET u.notification_num = 0, n.seen = 1
WHERE u.id = 2;
SELECT * FROM users;
+----+-------+----------------------+------------------+
| id | name | email | notification_num |
+----+-------+----------------------+------------------+
| 1 | John | John134#gmail.com | 4 |
| 2 | Peter | matrix_peter#ymail.c | 0 |
| 3 | Jack | jk_43m#gmail.com | 6 |
+----+-------+----------------------+------------------+
SELECT * FROM notifications;
+---------+---------+------+
| post_id | user_id | seen |
+---------+---------+------+
| 3243 | 1 | 1 |
| 3246 | 2 | 1 |
| 3764 | 3 | 1 |
| 4325 | 2 | 1 |
| 4346 | 2 | 1 |
| 5454 | 3 | 1 |
| 8765 | 3 | 0 |
+---------+---------+------+

Pass a value from a Table to another Table

I have this table, its name is puntajes:
+---------------+---------------+---------+
| estudiante_ID | evaluacion_ID | puntaje |
+---------------+---------------+---------+
| 1 | 1 | 15 |
| 2 | 1 | 11 |
| 3 | 1 | 17 |
| 4 | 1 | 12 |
| 1 | 2 | 13 |
| 2 | 2 | 8 |
| 3 | 2 | 15 |
| 4 | 2 | 16 |
| 1 | 3 | 9 |
| 2 | 3 | 14 |
| 3 | 3 | 9 |
| 4 | 3 | 10 |
| 1 | 4 | 15 |
| 2 | 4 | 16 |
| 3 | 4 | 9 |
| 4 | 4 | 12 |
+---------------+---------------+---------+
And I want to get the max score from puntaje column where evaluacion_ID is equal to 3, i want this value to be in the 'maxpuntaje 'column in the evaluaciones table, like an update , this is evaluaciones table:
+---------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+---------+----------------+
| fecha | date | NO | | NULL | |
| tipo | enum('P','E') | NO | | NULL | |
| maxpuntaje | int(11) | NO | | NULL | |
| clase_ID | int(10) unsigned | NO | | NULL | |
| evaluacion_ID | int(10) unsigned | NO | PRI | NULL | auto_increment |
+---------------+------------------+------+-----+---------+----------------+
both of the tables have the evaluacion_ID column
I've commented out WHERE conditions that limit the UPDATE and maximum puntaje value retrieval so that your query could be run for all evaluacion_ID. If you need it only for 3, remove the comment marks.
Using MySQL UPDATE JOIN syntax:
UPDATE evaluaciones e
LEFT JOIN (
SELECT evaluacion_ID, MAX(puntaje) maxpuntaje
FROM puntajes
-- WHERE evaluacion_ID = 3
GROUP BY evaluacion_ID
) p USING (evaluacion_ID)
SET maxpuntaje = p.maxpuntaje
-- WHERE e.evaluacion_ID = 3
I suspect you're looking for this query:
UPDATE evaluaciones
SET maxpuntaje = (
SELECT max(puntaje)
FROM puntajes
WHERE evaluacion_ID = evaluaciones.evaluacion_ID
)
WHERE evaluacion_ID = 3

How to join 3 tables in order to get a result with two tables alternating

Say I have 3 tables, foo bar and baz, where bar and baz having different additional informations about the datasets in foo. Is there a way to join these 3 tables together, so that in every output row is either a (foo <join> bar) or (foo <join> baz) dataset?
Say, I have the following tables:
mysql> select * from foo;
+----+-------+
| id | foo |
+----+-------+
| 1 | start |
| 2 | mid |
| 3 | end |
+----+-------+
mysql> select * from bar;
+----+-----+-----------+
| id | bid | bar |
+----+-----+-----------+
| 1 | 1 | bar-start |
| 2 | 2 | bar-mid |
| 3 | 3 | bar-end |
+----+-----+-----------+
mysql> select * from baz;
+----+-----+-------------+
| id | bid | baz |
+----+-----+-------------+
| 1 | 1 | baz-start-1 |
| 1 | 2 | baz-start-2 |
| 1 | 3 | baz-start-3 |
| 2 | 4 | baz-mid-1 |
| 2 | 5 | baz-mid-2 |
| 2 | 6 | baz-mid-3 |
| 3 | 7 | baz-end-1 |
| 3 | 8 | baz-end-2 |
| 3 | 9 | baz-end-3 |
+----+-----+-------------+
I can extract all the information with a query which joins those tables together via
mysql> select * from foo join bar join baz on foo.id = bar.id and foo.id=baz.id;
+----+-------+----+-----+-----------+----+-----+-------------+
| id | foo | id | bid | bar | id | bid | baz |
+----+-------+----+-----+-----------+----+-----+-------------+
| 1 | start | 1 | 1 | bar-start | 1 | 1 | baz-start-1 |
| 1 | start | 1 | 1 | bar-start | 1 | 2 | baz-start-2 |
| 1 | start | 1 | 1 | bar-start | 1 | 3 | baz-start-3 |
| 2 | mid | 2 | 2 | bar-mid | 2 | 4 | baz-mid-1 |
| 2 | mid | 2 | 2 | bar-mid | 2 | 5 | baz-mid-2 |
| 2 | mid | 2 | 2 | bar-mid | 2 | 6 | baz-mid-3 |
| 3 | end | 3 | 3 | bar-end | 3 | 7 | baz-end-1 |
| 3 | end | 3 | 3 | bar-end | 3 | 8 | baz-end-2 |
| 3 | end | 3 | 3 | bar-end | 3 | 9 | baz-end-3 |
+----+-------+----+-----+-----------+----+-----+-------------+
But I would like to get an output like the following table, since that would make the code in the application consuming the data much simpler:
+----+-------+------+------+-----------+------+------+-------------+
| id | foo | id | bid | bar | id | bid | baz |
+----+-------+------+------+-----------+------+------+-------------+
| 1 | start | 1 | 1 | bar-start | NULL | NULL | NULL |
| 1 | start | NULL | NULL | | 1 | 1 | baz-start-1 |
| 1 | start | NULL | NULL | | 1 | 2 | baz-start-2 |
| 1 | start | NULL | NULL | | 1 | 3 | baz-start-3 |
| 2 | mid | 2 | 2 | bar-mid | NULL | NULL | NULL |
| 2 | mid | NULL | NULL | | 2 | 4 | baz-mid-1 |
| 2 | mid | NULL | NULL | | 2 | 5 | baz-mid-2 |
| 2 | mid | NULL | NULL | | 2 | 6 | baz-mid-3 |
| 3 | end | 3 | 3 | bar-end | NULL | NULL | NULL |
| 3 | end | NULL | NULL | | 3 | 7 | baz-end-1 |
| 3 | end | NULL | NULL | | 3 | 8 | baz-end-2 |
| 3 | end | NULL | NULL | | 3 | 9 | baz-end-3 |
+----+-------+------+------+-----------+------+------+-------------+
Is there a way to convince mysql to give me a result set like the last one?
(
select foo.id as foo_id, foo.foo, bar.id, bar.bid, bar.bar, null, null as baz_bid, null as baz from foo
join bar on foo.id=bar.id
)
union
(
select foo.id as foo_id, foo.foo, null, null, '', baz.id, baz.bid as baz_bid, baz.baz from foo
join baz on foo.id=baz.id
)
order by foo_id asc, bar desc, baz_bid asc