MySQL INSERT INTO query column value equals another SQL SELECT query - mysql

Could anybody kindly guide me on correct direction for below query? It's not working under phpMyAdmin.
INSERT INTO `Setting`
(`id`, `type`, `name`, `value`, `parentId`, `createdAt`, `updatedAt`, `createdById`, `updatedById`)
VALUES
(NULL, 0, 'howItWorks', 'Some URL', NULL, NULL, NULL, -1, NULL),
(NULL, 0, 'howItWorksThumb', 'Some URL', (SELECT id FROM Setting WHERE name = 'howItWorks'), NULL, NULL, -1, NULL);
Same kind of query works under PostgreSQL.
Error I am getting: #1093 - You can't specify target table 'Setting' for update in FROM clause
Question is update to explained issues related to LAST_INSERT_ID() solutions:
To use LAST_INSERT_ID() solutions; child row should be inserting immediately after parent row.
I want to get the parentId for child row not immediately after I insert parent row. What will be the solution?
Also what if I want to add two children for same parent row?

MySQL doesn't allow you to SELECT in a subquery from the same table that you're inserting into in the main query. So you'll need to split this into two INSERT queries:
You can use LAST_INSERT_ID() to get the auto-increment ID that was assigned in the last INSERT, rather than using a subquery.
INSERT INTO `Setting` (`id`, `type`, `name`, `value`, `parentId`, `createdAt`, `updatedAt`, `createdById`, `updatedById`)
VALUES (NULL, 0, 'howItWorks', 'Some URL', NULL, NULL, NULL, -1, NULL);
INSERT INTO `Setting` (`id`, `type`, `name`, `value`, `parentId`, `createdAt`, `updatedAt`, `createdById`, `updatedById`)
VALUES (NULL, 0, 'howItWorksThumb', 'Some URL', LAST_INSERT_ID(), NULL, NULL, -1, NULL);
Unfortunately, using LAST_INSERT_ID() still doesn't allow you to combine them into a single query, because it calls the function before doing any inserts.
If you're doing the second insert later, you can do it with a normal INSERT ... SELECT ...:
INSERT INTO `Setting` (`id`, `type`, `name`, `value`, `parentId`, `createdAt`, `updatedAt`, `createdById`, `updatedById`)
SELECT NULL, 0, 'howItWorksThumb', 'Some URL', id, NULL, NULL, -1, NULL
FROM Setting
WHERE name = 'howItWorks'

DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
, type TINYINT NOT NULL
, name VARCHAR(100) NOT NULL
, value VARCHAR(100) NOT NULL
, parentId INT NULL
, createdById INT NOT NULL
);
It would be sensible to bind the following into a transaction.
INSERT INTO my_table
( type
, name
, value
, createdById
)
VALUES
( 0
, 'howItWorks'
, 'Some URL'
, -1
);
INSERT INTO my_table
( type
, name
, value
, parentId
, createdById
)
SELECT 0
, 'howItWorksThumb'
, 'Some URL'
, LAST_INSERT_ID()
, -1
FROM my_table;
End of transaction
SELECT * FROM my_table;
+----+------+-----------------+----------+----------+-------------+
| id | type | name | value | parentId | createdById |
+----+------+-----------------+----------+----------+-------------+
| 1 | 0 | howItWorks | Some URL | NULL | -1 |
| 2 | 0 | howItWorksThumb | Some URL | 1 | -1 |
+----+------+-----------------+----------+----------+-------------+

see the data type of the table that you created. and see also DEFAULT on the field that you create. If ID is NULL should DEFAULT = auto_increment.

Related

MySQL group by fill gaps

I need to group by a field and fill missing information if any.
For example, we have a test table:
CREATE TEMPORARY TABLE `test` (
`name` VARCHAR(100), `description` VARCHAR(100)
);
For this table, we have the following records:
INSERT INTO `test` (`name`, `description`, `email`)
VALUES ('John', '', ''),
VALUES ('John', 'Description #1', ''),
VALUES ('John', 'Description #2', ''),
VALUES ('John', '', 'john#example.com'),
VALUES ('John', '', '');
I need to select all entries on this table grouped by name and filling gaps, such as description (in this case, it should use 'Description #2' as it is the latest non-empty value for description. Same goes for email, it should return 'john#example.com'.
How should I select these values?
PS: the actual table have several columns, so it would be good to not modify the SELECT statement.
My current select is:
SELECT `name`, `description` FROM `test` GROUP BY `name`;
The problem is it will always use the first occurrence values. I need to "merge" all values based on latest non-empty insertion.
Each column may end up using values from different entries.
Expected output:
____________________________________________
| name | description | email |
--------------------------------------------
| John | Description #2 | john#example.com |
--------------------------------------------
Thanks.
You'll have to make explicit what does "last" actually mean. The records you inserted don't have any specific order, so you'll have to add either an autoincrementing id, or something like created_at date.
Then, you can choose the right records using:
SELECT `name`, `description`
FROM `test`
GROUP BY `name`
HAVING `created_at` = MAX(`created_at`)
For the non-empty part, you'll have to filter them using WHERE description<>''.

How to transform (or possibly pivot) these MySQL results into a consolidated view?

The result of a MySQL query look like this:
key | name | value
----+------+--------
1 | foo | alpha
1 | bar | beta
2 | foo | charlie
2 | bar | delta
3 | foo | echo
How can I transform the result into this?
key | foo | bar
----+---------+--------
1 | alpha | beta
2 | charlie | delta
3 | echo |
I would prefer a SQL solution, but the result is being passed into PHP so I could manipulate the result using PHP if there is no SQL solution. I am reluctant to use PHP however as I have a feeling it will be very slow for queries where there may be a thousand or more different values in the key column.
I have heard the term pivoting being used when I searched for an answer on Google. I don't fully understand what that means though so I'm not sure if pivoting is relevant here.
Thanks in advance for any suggestions.
Just use conditional aggregation:
select `key`,
max(case when name = 'foo' then value end) as foo,
max(case when name = 'bar' then value end) as bar
from t
group by `key`;
If you have multiple values for each key, then group_concat() might be more appropriate than max().
If you don't know the list of possible names, then Google "MySQL dynamic pivot" for examples of what to do. That requires using dynamic SQL.
Although Gordon Linoff's solution was the accepted answer I have decided to add an example of how I implemented it. This should help anyone who stumbles across this question in the future!
-- create a table
CREATE TABLE `items` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`uuid` INT NOT NULL,
`key` VARCHAR(255) NOT NULL,
`value` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
-- insert some rows
INSERT INTO `items` (`id`, `uuid`, `key`, `value`) VALUES ('1', '1', 'name', 'Foo');
INSERT INTO `items` (`id`, `uuid`, `key`, `value`) VALUES ('2', '1', 'price', '100');
INSERT INTO `items` (`id`, `uuid`, `key`, `value`) VALUES ('3', '2', 'name', 'Bar');
INSERT INTO `items` (`id`, `uuid`, `key`, `value`) VALUES ('4', '2', 'price', '200');
INSERT INTO `items` (`id`, `uuid`, `key`, `value`) VALUES ('5', '3', 'name', 'Baz');
-- and fetch them
SELECT `uuid`,
MAX(IF((`key` = 'name'), `value`, NULL)) AS `name`,
MAX(IF((`key` = 'price'), `value`, NULL)) AS `price`
FROM `items`
GROUP BY `uuid`;

Null or empty instead of 0

I created a new table with:
CREATE TABLE `test`.`tab1` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(50) NULL , `age` INT NULL , PRIMARY KEY (`id`));
When I insert a new row, but want to keep age empty, I do:
INSERT INTO `tab1` (`id`, `Name`, `Age`) VALUES (NULL, 'Peter', '');
I get this entry:
| id | name | age |
|----|-------|-----|
| 1 | Peter | 0 |
Why the age column just doesn't remain empty or NULL?
How can I set a default value, so that it just remains empty, when no value is specified while inserting?
Since the column is of type int the DB tries to convert the string '' to a number. That would be 0.
Just use null instead of '' if you don't have a value. That is what null is for.

Using Join and Insert Statement in MySQL

I have an insert statement like this
INSERT INTO T_WorkContents ( user_id, working_date, working_start_time,
working_end_time, break_time, holiday_mark,
overtime_hours, overtime_reason, work_detail,
remarks, regist_user, regist_date,
update_user, update_date )
VALUES ( '00005', '2015-02-05', '8:0',
'17:0', '0:0', '0',
'0:0', NULL, NULL,
NULL, '00005', current_timestamp(),
'00005', current_timestamp()
);
I want to check whether the user is already deleted when insert the new row by join the table workcontent with the table user info on user_id and the condition is where userinfo.delete_flag = 0.
is there any way to do it?
I'm not sure I understand your question. But if you would like to only perform the insertion if the corresponding user exists and is marked as not deleted in your other table this should work:
INSERT INTO T_WorkContents ( user_id, working_date, working_start_time,
working_end_time, break_time, holiday_mark,
overtime_hours, overtime_reason, work_detail,
remarks, regist_user, regist_date,
update_user, update_date )
SELECT '00005', '2015-02-05', '8:0',
'17:0', '0:0', '0',
'0:0', NULL, NULL,
NULL, '00005', current_timestamp(),
'00005', current_timestamp()
FROM userinfo ui
WHERE ui.user_id = '00005' && ui.delete_flag = 0
If the userinfo doesn't contain a row with a user_id equal to 00005 and a delete_flag that is set to 0 then the select will return no rows and the insert query will in turn affect no rows.
You can use WHERE EXISTS. Try below
INSERT INTO funds (field1, field2)
values (x, xx)
WHERE EXISTS (
SELECT *
FROM table
WHERE userid = your_user_id
);

mysql query - insert data unix_timestamp ( now ( ) ) issue

I have an INT (11) column for storing the current timestamp in seconds. The query looks like:
INSERT INTO `abc` (id, timestamp) VALUES ('', UNIX_TIMESTAMP ( NOW () ) )
I don't know why, but the date isn't changed. It doesn't matter when I send the query, the column value isn't changed. It has 1342692014 value, but I don't know why.
Is there any option or other function for timestamps? I must store dates in seconds.
You never refer to the timestamp column in your query. You only have a string:
INSERT INTO `abc` (id, 'timestamp') VALUES ('', UNIX_TIMESTAMP ( NOW () ) )
^^^^^^^^^^^
Edit:
I get this with your updated code:
ERROR 1630 (42000): FUNCTION test.NOW does not exist. Check the
'Function Name Parsing and Resolution' section in the Reference Manual
Assuming it's not still the actual code and after fixing the syntax error, I can't reproduce your results. My educated guess is that id is an auto-incremented integer primary key, your current SQL mode is making MySQL take '' as NULL and inserting a new row... But I haven't really tested this hypothesis.
My working code is this:
CREATE TABLE `abc` (
`pk` INT(10) NOT NULL AUTO_INCREMENT,
`id` VARCHAR(10) NULL DEFAULT NULL,
`timestamp` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`pk`)
)
ENGINE=InnoDB;
INSERT INTO abc (id, timestamp) VALUES ('', UNIX_TIMESTAMP());
-- Wait a few seconds
INSERT INTO abc (id, timestamp) VALUES ('', UNIX_TIMESTAMP());
-- Wait a few seconds
INSERT INTO abc (id, timestamp) VALUES ('', UNIX_TIMESTAMP());
SELECT timestamp FROM abc WHERE id='';
... and returns this:
+------------+
| timestamp |
+------------+
| 1342694445 |
| 1342694448 |
| 1342694450 |
+------------+
3 rows in set (0.00 sec)