insert into table(var1) select from itself - mysql

I want to insert into the last column (number of people in that room) and
I want to use
insert into table(n_people_in_room)
select count(people_id)
from table
group by room
This is obvious wrong because i need to join the table with itself on people_id but i didn't. What is the right code?

Here's one way to do it, using an inline view to get the N_People_In_Room totals:
I'd do it as a SELECT first:
SELECT t.peopleid
, t.room
, t.n_people_in_room AS `old_npir`
, s.n_people_in_room AS `new_npir`
FROM mytable t
JOIN ( SELECT c.room
, COUNT(1) AS n_people_in_room
FROM mytable c
GROUP BY c.room
) s
ON s.room = t.room
Convert that into an UPDATE by repacing SELECT ... FROM with UPDATE, and adding a SET clause...
UPDATE mytable t
JOIN ( SELECT c.room
, COUNT(1) AS n_people_in_room
FROM mytable c
GROUP BY c.room
) s
ON s.room = t.room
SET t.n_people_in_room = s.n_people_in_room

Related

Selecting maximum column and row id

Is there a way to tell MySQL that while making something like this
SELECT id, MAX(seq) FROM t1 GROUP BY ident;
I can also get the id value? I know I shouldn't be using id if it's not in a group by but I feel like its strange to make a multi pass to get the row ids with the maximum seq field when it already passed it. So what is the most effective way to do this? id is the primary key
SELECT a.*
FROM tableName
INNER JOIN
(
SELECT ident, MAX(seq) seq
FROM tableName
GROUP BY ident
) b ON a.ident = b.ident AND
a.seq = b.seq
Mabye:
SELECT MAX(a.seq), (SELECT id FROM t1 as b where b.ident=a.ident AND MAX(a.seq) = b.seq LIMIT 1) as id FROM t1 AS a GROUP BY a.ident;
Fiddle
Try using self-join:
SELECT t1.* FROM MyTable t1
JOIN
(SELECT ident, MAX(seq) AS MAX_Seq
FROM MyTable
GROUP BY ident
) t2
ON t1.seq = t2.MAX_Seq
AND t1.ident = t2.ident
See this sample SQLFiddle
What is seq exactly ?
I guess you can also order your results ?
SELECT id FROM t1 GROUP BY ident ORDER BY seq DESC
Regarding to the others answer, seq is in another table ?

MYSQL Update a huge SQL query

In my system I want to get attendance data of employee from the DB, so I wrote a huge SQL query, and it gives me relevant details. But now I need an updated version of particular results. So I don’t know how to put this query within the update statement.
select * from(
select concat('pre:', date) as date,concat('pre:',employee_no) as employee_no,concat('pre:',name_with_initials) as name,concat('pre:',sign_in_at) as sign_in_at,concat('pre:',sign_out_at) as sign_out_at,emp from( SELECT date, present.employee_no,employee_details.name_with_initials,present.sign_in_at, present.sign_out_at,employee_details.employee_no as emp from (
SELECT employee_no,date,sign_in_at,sign_out_at FROM complete_shifts WHERE date = '2013-06-17' UNION ALL
SELECT employee_no,date,sign_in_at,'00:00:00 ' AS sign_out_at FROM incomplete_shifts WHERE date = '2013-06-17' UNION ALL
SELECT employee_no,date,sign_in_at,'00:00:00 ' AS sign_out_at FROM incomplete_shift_records WHERE date = '2013-06-17'
)as present inner join employee_details on present.employee_no = employee_details.employee_no
) as final_present
union all
select concat('ab:',date)as date,concat('ab:',employee_no)as employee_no,concat('ab:',name_with_initials)as name,concat('ab:',sign_in_at)as sign_in_at,concat('ab:',sign_out_at)as sign_out_at, emp from(
select '2013-06-17' AS date,absent.employee_no,employee_details.name_with_initials,'00:00:00'as sign_in_at , '00:00:00' as sign_out_at,employee_details.employee_no as emp from (
select * from ( SELECT employee_details.employee_no FROM employee_details left outer join resigned_emps on
employee_details.employee_no = resigned_emps.employee_no where resigned_emps.date is null or resigned_emps.date>'2013-06-17'
) as available_emps left outer join (
select employee_no from complete_shifts where date = '2013-06-17' union
select employee_no from incomplete_shifts where date = '2013-06-17' union
select employee_no from incomplete_shift_records where date = '2013-06-17'
) as present on available_emps.employee_no = present.employee_no where present.employee_no is null
) as absent inner join employee_details on absent.employee_no = employee_details.employee_no
) as final_absent
)as final left outer join( SELECT leave.employee_no as lv_emp
FROM leave_dates inner join leave on leave_dates.leave_id = leave.leave_id where leave_dates.date = '2013-06-17')as leave_emps
on final.emp = leave_emps.lv_emp;
With such a large query, you should just put the results in a temporary table and update from that.
create temporary table toupdate as
<your query goes here>;
Now you can investigate the data that will be updated, to be sure that it really is ok.
Next you can do the update as a join:
update table_to_update t join
toupdate
on t.key = toupdate.key
set t.col = toupdate.col
Because you don't give the column or table details, this is just the structure of such a solution.
Instead of "select *", use the appropriate unique field to fetch the records to update, ex EmpID. Finally use this result as inner query result to update query.
Example
Update ... set ... where empid in (your select query goes here)

using the same field within a subquery of mysql

how can i make something like this work?
INSERT INTO age.page(domain,title_count,youtube_count,ipaddress,updated)
SELECT * FROM
(
SELECT domain,
COUNT(domain) AS titlecount,
(SELECT COUNT(*) FROM table2 WHERE title = table1.title) AS YoutubeCount, ipaddress
NOW() AS timeNow
FROM table1
GROUP BY domain
ORDER BY title DESC
) a;
I want to use a subquery to get a count of a different table but use the same field from the main query.
the reason i want to do this is so i dont have to run two queries instead its only one.
You can do this COUNT in a subquery and then JOIN it with the first table:
INSERT INTO age.page(domain, title_count, youtube_count, ipaddress, updated)
SELECT * FROM
(
SELECT
domain,
COUNT(domain) AS titlecount,
t2.titlecount AS YoutubeCount,
ipaddress,
NOW() AS timeNow
FROM table1
INNER JOIN
(
SELECT title, COUNT(*) Titlecount
FROM table2
GROUP BY title
) AS t2 ON t2.title = table1.title
GROUP BY domain
ORDER BY table1.title DESC
) a;

WITH clause in MySQL?

Does MySQL support common table expressions? For example in Oracle there's the WITH clause? :
WITH aliasname
AS
( SELECT COUNT(*) FROM table_name )
SELECT COUNT(*) FROM dept,aliasname
SELECT t.name,
t.num
FROM TABLE t
JOIN (SELECT c.id,COUNT(*) 'num1'
FROM TABLE1 c
WHERE c.column = 'a'
GROUP BY c.id) ta1 ON ta1.id = t.id
JOIN (SELECT d.id,COUNT(*) 'num2'
FROM TABLE2 d
WHERE d.column = 'a'
GROUP BY d.id) ta2 ON ta2.id = t.id
One way is to use a subquery:
SELECT COUNT(*)
FROM dept,
(
SELECT COUNT(*)
FROM table_name
) AS aliasname
Note that the , between the two tables will cross join the two tables the same as in your query you posted. IF there is any relation between them you can JOIN them instead.
No, MySQL does not support Common Table Expressions (CTE). So instead of using WITH tablealias as (....), you will have to do a subquery.
For example,
WITH totalcount AS
(select userid, count(*) as tot from logins group by userid)
SELECT a.firstname, a.lastname, b.tot
FROM users a
INNER JOIN
totalcount b
on a.userid = b.userid
can be re-written in MySQL as
SELECT a.firstname, a.lastname, b.totalcount
FROM users a
INNER JOIN
(select userid, count(*) as tot from logins group by userid) b
on a.userid = b.userid
So let's talk about WITH clause .
WITH clause and INNER JOIN otherwise JOIN are a kind of same , but WITH clause gives you much more latitude especially in WHERE clause ;
I am going to make a view that'll get values like count of users , user name and etc.
First (Creating our tables users and inserted_users) :
inserted_users table :
CREATE TABLE users (id BIGINT(10) AUTO INCEREMENT PRIMARY KEY , name VARCHAR(50))
users table :
CREATE TABLE users (id BIGINT(10) AUTO INCEREMENT PRIMARY KEY , name VARCHAR(50) , gender TINYINT(1))
Second (Inserting some values to work with) :
users table :
INSERT INTO users (name,gender) VALUES ('Abolfazl M' , 1)
I don't want to insert into inserted_users by query , but I want to add a TRUGGER which will insert data automatically to users_inserted table before data be inserted into users table.
Third (Creating trigger add_uinserted) :
DELIMITER $$
CREATE TRIGGER IF NOT EXISTS add_uinserted BEFORE INSERT ON users FOR EACH ROW
BEGIN
IF NEW.name <> '' THEN
INSERT INTO users_inserted (name) VALUES (NEW.name);
ELSE
INSERT INTO users (name,gender) VALUES ('Unknown',NEW.gender);
INSERT INTO users_inserted (name) VALUES ('Unknown');
END IF;
END$$
DELIMITER ;
Run the query and the trigger will be created and at last let's create a view to give us result from a query having WITH clause .
CREATE VIEW select_users AS
WITH GetCAll AS (
SELECT u1.id As Uid ,COUNT(u1.name) AS CnAll FROM users u1
)
SELECT u1.name AS NAME,CASE
WHEN s1.gender = 1 THEN "MALE"
WHEN s1.gender = 0 THEN "FEMALE"
ELSE "UNKNOWN"
END AS GENDER,CASE
WHEN u1.id = gca.Uid THEN "INSERTED TO users_inserted"
ELSE "NOT INSERTED TO users_inserted"
END AS INSERTED,gca.CnAll FROM GetCAll AS gca INNER JOIN users u1;
After you query got ran the view will be created and by calling the view select_users the data will be shown
Last step (calling the select_users view) :
SELECT * FROM select_users
Thanks for taking a look at my answer , and that's it !!

MySQL select with min

I need to select fields message and username from table list where list_id=1 (it can be 2 or 5 etc) with minimal number value (min(number)). How can i do it?
I tried it:
SELECT `message`,`username` FROM `list` WHERE `list_id`=2 AND min(`number`)
But it not work.
Try so
SELECT `message`,`username`
FROM `list`
WHERE `list_id` = 2
ORDER BY `number` ASC
LIMIT 1
SELECT
a.*
FROM list
INNER JOIN (
SELECT
`message`,
`username`,
MIN(`number`)
FROM `list`
WHERE `list_id`=2
) as a on a.id = list.id