Select rows that have at least one set member [duplicate] - mysql

This question already has answers here:
Query with multiple values in a column
(4 answers)
Closed 6 years ago.
I am having a problem with my sql command.
So I have a column of type SET let's call it test_set, and I have multiple values that a row can have, let's say test1, test2
And let's say I have one row that has test1,
and another that has test1 and test2,
How could I select all rows that have test1, (should return both rows)
What about all rows that have test2 (Should return the second row)
As of right now, I know you can do SELECT * WHERE test_set='test1'
But this only returns rows that only have test1, not the ones that have test1 and test2.
Thanks!

If I am understanding you correctly you have a VARCHAR column containing comma delimited values.
In that case a LIKE will work for you.
SELECT * WHERE test_set LIKE '%test1%'
You might want to consider changing the database schema if you can though - For example have a separate "SETS" table that references your original table.
Ex.
CREATE TABLE MY_DATA (ID INT NOT NULL, NAME VARCHAR(255) NULL)
CREATE TABLE SETS (ID INT NOT NULL, MY_DATA_ID INT NOT NULL, SET_ITEM VARCHAR(50) NOT NULL)
SELECT *
FROM MY_DATA D
JOIN SETS S
ON S.MY_DATA_ID = D.ID
WHERE S.SET_ITEM = 'test1'

Related

MYSQL: How to update unique random number to existing rows

It's been my first question to this website, I'm sorry if I used any wrong keywords. I have been with one problem from quite a few days.
The Problem is, I have a MYSQL table named property where I wanted to add a ref number which will be a unique 6 digit non incremental number so I alter the table to add a new column named property_ref which has default value as 1.
ALTER TABLE property ADD uniqueIdentifier INT DEFAULT (1) ;
Then I write a script to first generate a number then checking it to db if exist or not and If not exist then update the row with the random number
Here is the snippet I tried,
with cte as (
select subIdentifier, id from (
SELECT id, LPAD(FLOOR(RAND() * (999999 - 100000) + 100000), 6, 0) AS subIdentifier
FROM property as p1
WHERE "subIdentifier" NOT IN (SELECT uniqueIdentifier FROM property as p2)
) as innerTable group by subIdentifier
)
UPDATE property SET uniqueIdentifier = (
select subIdentifier from cte as c where c.id = property.id
) where property.id != ''
this query returns a set of record for almost all the rows but I have a table of entries of total 20000,
but this query fills up for ~19000 and rest of the rows are null.
here is a current output
[current result picture]
If anyone can help, I am extremely thanks for that.
Thanks
Instead of trying to randomly generate unique numbers that do not exist in the table, I would try the approach of randomly generating numbers using the ID column as a seed; as long as the ID number is unique, the new number will be unique as well. This is not technically fully "random" but it may be sufficient for your needs.
https://www.db-fiddle.com/f/iqMPDK8AmdvAoTbon1Yn6J/1
update Property set
UniqueIdentifier = round(rand(id)*1000000)
where UniqueIdentifier is null
SELECT id, round(rand(id)*1000000) as UniqueIdentifier FROM test;

Column 'name' cannot be null [duplicate]

This question already has answers here:
Mysql Table Column Cannot Be Null
(1 answer)
mysql - "column cannot be null"
(2 answers)
Closed 4 years ago.
I have read a lot of different posts trying to figure out why my code isn't working but the goal here is to set the value of the column 'name' to null when column 'mark' is below 69. My code is:
CREATE PROCEDURE gradesReport()
BEGIN
SELECT name FROM students WHERE mark > 69;
UPDATE students SET name = NULL WHERE mark < 69;
END
The first statement works fine but then I get the error that column name cannot be null.
It could be that the column name is declared as not null
You should firstly changed it into a NOT NULL Column
ALTER TABLE students
CHANGE `name` varchar(255) NULL;
Here is another way of making a column nullable in MySQL:
ALTER TABLE students MODIFY name VARCHAR(255);
Columns are nullable by default in MySQL, so we don't actually need to specify NULL in the alter statement.

Avoid anonymous fields in JSON built from table rows [duplicate]

This question already has answers here:
Using row_to_json() with nested joins
(3 answers)
Return multiple columns of the same row as JSON array of objects
(2 answers)
Closed 8 years ago.
I have a table:
CREATE TABLE test (
item_id INTEGER NOT NULL,
item_name VARCHAR(255) NOT NULL,
mal_item_name VARCHAR(255),
active CHAR(1) NOT NULL,
data_needed CHAR(1) NOT NULL,
parent_id INTEGER);
The query:
select array_to_json(array_agg(row_to_json(t)))
from (select item_id as id,
item_name as text,
parent_id as parent,
(mal_item_name,data_needed) as data
from test) t
produces result:
[{"id":1,"text":"Materials","parent":0, "data": {"f1":null,"f2":"N"}},
{"id":2,"text":"Bricks","parent":1, "data":{"f1":null,"f2":"N"}},
{"id":3,"text":"Class(high)","parent":2, "data":{"f1":null,"f2":"Y"}},
{"id":4,"text":"Class(low)","parent":2, "data":{"f1":null,"f2":"Y"}}]
The original field names mal_item_name and data_needed are replaced with f1 and f2.
How can I get a JSON with field names itself? Documentation says by creating a type for these two fields. Is there an alternative?
Use json_build_object() in Postgres 9.4 or later:
SELECT json_agg(t) AS js
FROM (SELECT item_id AS id
, item_name AS text
, parent_id AS parent
, json_build_object('mal_item_name', mal_item_name
,'data_needed', data_needed) AS data
FROM test) t;
And use json_agg(...) instead of array_to_json(array_agg(row_to_json(...))).
For Postgres 9.3:
SELECT json_agg(t) AS js
FROM (SELECT item_id AS id
, item_name AS text
, parent_id AS parent
, (SELECT t FROM (SELECT mal_item_name, data_needed)
AS t(mal_item_name, data_needed)) AS data
FROM test) t;
Details:
Return multiple columns of the same row as JSON array of objects
Using row_to_json() with nested joins
PostgreSQL : select columns inside json_agg

Copy row from one table to another with a additional primary key

I tried this:
INSERT INTO event_log_tracker_table
SELECT * FROM event_tracker_table WHERE eventid = '560'
However I get this error:
Error Code: 1136. Column count doesn't match value count at row 1
The columns match exactly the same except for one thing...
I added one more column (eventlogid) in event_log_tracker_table to be a primary key. How can I insert a row, from another table and have it add to a primary key in the new table?
Below is a structure of the tables.
event_log_tracker_table (24 columns)
-----------------------
eventlogid - PK
eventid - INT
//
// 22 other columns
//
event_tracker_table (23 columns)
-----------------------
eventid - PK
//
// 22 other columns
//
I have tried to do this:
INSERT INTO event_log_tracker_table
SELECT null, * FROM event_tracker_table WHERE eventid = '560'
As documented under SELECT Syntax:
Use of an unqualified * with other items in the select list may produce a parse error. To avoid this problem, use a qualified tbl_name.* reference
SELECT AVG(score), t1.* FROM t1 ...
Therefore, instead of SELECT NULL, * you could should qualify the wildcard:
INSERT INTO event_log_tracker_table
SELECT NULL, event_tracker_table.*
FROM event_tracker_table
WHERE eventid = '560'

How can I create a query that shows children of an item recursively [duplicate]

This question already has answers here:
Recursive MySQL Query with relational innoDB
(2 answers)
Closed 9 years ago.
I have a MySQL table which has the following format:
CREATE TABLE IF NOT EXISTS `Company` (
`CompanyId` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`Name` VARCHAR(45) NULL ,
`Address` VARCHAR(45) NULL ,
`ParentCompanyId` INT UNSIGNED NULL ,
PRIMARY KEY (`CompanyId`) ,
INDEX `fk_Company_Company_idx` (`ParentCompanyId` ASC) ,
CONSTRAINT `fk_Company_Company`
FOREIGN KEY (`ParentCompanyId` )
REFERENCES `Company` (`CompanyId` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
So to clarify, I have companies which can have a parent company. This could result in the following example table contents:
CompanyId Name Address ParentCompanyId
1 Foo Somestreet 3 NULL
2 Bar Somelane 4 1
3 McD Someway 1337 1
4 KFC Somewhere 12 2
5 Pub Someplace 2 4
Now comes my question.
I want to retrieve all children of CompanyId 2 recursive. So the following result set should appear:
CompanyId Name Address ParentCompanyId
4 KFC Somewhere 12 2
5 Pub Someplace 2 4
I thought of using the With ... AS ... statement, but it is not supported by MySQL. Another solution I thought of was using a procedure or function which returns a result set and union it with the recursive call of that function. But MySQL does only support column types as return values.
The last possible solution I thought about was to create a table with two fields: CompanyId and HasChildId. I could then write a procedure that loops recursively through the companies and fills the table with all recursive children by a companyid. In this case I could write a query which joins this table:
SELECT CompanyId, Name, Address
FROM Company C -- The child
INNER JOIN CompanyChildMappingTable M
ON M.CompanyId = C.HasChildId
INNER JOIN Company P -- The parent
ON P.CompanyId = M.CompanyId
WHERE P.CompanyId = 2;
This option should be a fast one if i'd call the procedure every 24 hours and fill the table on the fly when new records are inserted into Company. But this could be very tricky and I should do this by writing triggers on the Company table.
I would like to hear your advice.
Solution: I've built the following procedure to fill my table (now it just returns the SELECT result).
DELIMITER $$
DROP PROCEDURE IF EXISTS CompanyFillWithSubCompaniesByCompanyId$$
CREATE PROCEDURE CompanyFillWithSubCompaniesByCompanyId(IN V_CompanyId BIGINT UNSIGNED, IN V_TableName VARCHAR(100))
BEGIN
DECLARE V_CONCAT_IDS VARCHAR(9999) DEFAULT '';
DECLARE V_CURRENT_CONCAT VARCHAR(9999) DEFAULT '';
SET V_CONCAT_IDS = (SELECT GROUP_CONCAT(CompanyId) FROM Company WHERE V_CompanyId IS NULL OR ParentCompanyId = V_CompanyId);
SET V_CURRENT_CONCAT = V_CONCAT_IDS;
IF V_CompanyId IS NOT NULL THEN
companyLoop: LOOP
IF V_CURRENT_CONCAT IS NULL THEN
LEAVE companyLoop;
END IF;
SET V_CURRENT_CONCAT = (SELECT GROUP_CONCAT(CompanyId) FROM Company WHERE FIND_IN_SET(ParentCompanyId, V_CURRENT_CONCAT));
SET V_CONCAT_IDS = CONCAT_WS(',', V_CONCAT_IDS, V_CURRENT_CONCAT);
END LOOP;
END IF;
SELECT * FROM Company WHERE FIND_IN_SET(CompanyId, V_CONCAT_IDS);
END$$
Refer:
Recursive MySQL Query with relational innoDB
AND
How to find all child rows in MySQL?
It shall give a idea of how such a data structure, can be dealt in MYSQL
One quickest way to search is, use company id values in power of 2. companyId = parentId * 2 then query database like, select * from company where ((CompanyId % $parentId) == 0 )
I tried this code, it's quick but problem is it creates child's id as parentId * 2 and if depth of child goes deep, int, float may go out of range. So, I re-created my whole program.