My mysql table looks like the following:
CREATE TABLE "my_table" (
"id" int(11) NOT NULL AUTO_INCREMENT,
"content" blob NOT NULL,
"business_id" varchar(255) NOT NULL
PRIMARY KEY ("id")
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=latin1;
This table can contains several lines with the same "business_id". I want to make the business_id column unique. For this, I want to delete all lines which share a business_id except the last one.
For example, if I have the following lines
10 'hello' '5'
...
21 'hello' '5'
...
350 'hello' '5'
I want to delete lines of id 10 and 21.
I'm stuck on how to write the delete query. I don't know how to express that constraint.
Backup your DB before deletion:
delete FROM my_table where business_id in
(select business_id from (select business_id from my_table group by business_id having count(business_id)>1) t)
and business_id not in
(select maxid from (select max(business_id) maxid from my_table group by business_id having count(business_id)>1) t1);
Related
I want to delete some rows in a table. However the delete condition is not direct.This is just 1 table CUSTOMER:
CREATE TABLE customer (
CUST_ID int(11) NOT NULL AUTO_INCREMENT,
PRODUCT_CODE varchar(50) NOT NULL,
USER_NAME varchar(150) NOT NULL,
PRIMARY KEY (CUST_ID)
) ENGINE=InnoDB AUTO_INCREMENT=2455046 DEFAULT CHARSET=latin1;
Here is what works for me:
select cust_id from CUSTOMER where user_name = '20012';
Then use the resulting cust_id in the following DELETE ($cust_id is result of query 1)
delete from CUSTOMER where cust_id = $cust_id
Note: This can only delete one user_name . Also I want to do this in 1 query, not 2.
CUSTOMER t1
LEFT JOIN (
SELECT
cust_id id
FROM
CUSTOMER
where
user_name IN ('20012', '20013', '20014')
) t2 ON t1.cust_id = t2.id
The above apparently did not work.
You are unnecessarily complicating the logic. Instead of first getting all the customer id(s), for the given user_name values, you could simply filter on the user_name values. It is simply this:
DELETE FROM CUSTOMER WHERE user_name IN ('20012', '20013', '20014')
I have two tables topics and assessments the topics table is a basic table with id and name and in assessment table there is a JSON column called topic_list where array of topics is stored. I need the list of topics for a specific assessment with id and name.
CREATE TABLE `topics` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL COMMENT 'topic name will capture here',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1
CREATE TABLE `assessments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`topic_list` json DEFAULT NULL,
`assessment_name` varchar(150) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1
INSERT INTO `topics` (name) values
('topic1'),
('topic2'),
('topic3');
INSERT INTO `assessments` (topic_list, assessment_name) values
('[1,2]','assessment1'),
('[2,3]', 'assessment2'),
('[1,3]', 'assessment3');
SELECT t1.id,t1.name FROM topics AS t1
WHERE id IN (SELECT topic_list FROM assessments WHERE id = 1)
This is what I have tried but just getting first row:
SELECT id,name from topics where id in(select JSON_UNQUOTE(TRIM(TRAILING ']' FROM TRIM(LEADING '[' FROM JSON_EXTRACT(topic_list, '$[*]')))) from assessments where id = 1)
What I got is:
1 topic1
Results just first column from the array.
I was trying for:
1 topic1
2 topic2
You can use one of the following solutions using JSON_EXTRACT and JSON_CONTAINS:
SELECT id, name
FROM topics WHERE (
SELECT JSON_CONTAINS(
JSON_EXTRACT(topic_list, '$[*]'),
CONVERT(topics.id, JSON)
) FROM assessments WHERE id = 1
);
... or (with INNER JOIN):
SELECT topics.id, topics.name
FROM topics INNER JOIN assessments
ON JSON_CONTAINS(JSON_EXTRACT(topic_list, '$[*]'), CONVERT(topics.id, JSON)) = 1
WHERE assessments.id = 1
demo on dbfiddle.uk
Note: A faster solution can be an additional table with the mapping between topics and assessments instead of saving the topics list in the assessment record itself.
I need to obtain records in a key-value table with the following structure:
CREATE TABLE `PROPERTY` (
`id` int(11) NOT NULL,
`key` varchar(64) NOT NULL,
`value` text NOT NULL,
PRIMARY KEY (`id`,`key`)
);
I need to get all ids that have MULTIPLE specific key-value entries. For example, all ids that have keys "foo", "bar", and "foobar".
Simply use GROUP BY to group and then check the group count to count multiple values:
Select
id
from
`PROPERTY`
group by
key, value
having
count(*) > 1
Given updated question...
since you know the specific keys, you also know how many there are... so a count distinct in having should do it... along with a where...
SELECT id
FROM `PROPERTY`
Where key in ('foo','bar','foobar')
GROUP BY ID
having count(distinct key) = 3
I f you need the id of all the rows for key,value count(= >1)
select id from `PROPERTY`
where (key, value) in (select key, value from `PROPERTY`group by
key, value
having
count(*) > 1)
In my db I've a table (t1) with this structure
CREATE TABLE IF NOT EXISTS 't1' (
'id_ric' int(11) NOT NULL AUTO_INCREMENT,
'id_tipoins' decimal(1,0) NOT NULL,
'datains' timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ('id_ric')
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I create a view to count all record grouped by id_user in this way
CREATE VIEW view_users_app
AS
SELECT id_user, MAX(datains) last_datains, COUNT(*) totalCount
FROM t1
GROUP BY id_user
Now I'd like also count where id_tipoins = 1 and id_tipoins = 2 (grouped by id_user).
It's possible to do? How could I do this? Thanks
CREATE VIEW view_users_app
AS
SELECT id_user,
MAX(datains) last_datains,
COUNT(*) totalCount,
sum(id_tipoins = 1) as p1,
sum(id_tipoins = 2) as p2
FROM t1
GROUP BY id_user
i need some query.
CREATE TABLE `location_areas_localized` (
`id` int(11) DEFAULT NULL,
`lang_index` varchar(5) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
KEY `id` (`id`),
KEY `lang_index` (`lang_index`),
KEY `name` (`name`),
FULLTEXT KEY `name_2` (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `location_areas_localized` (`id`, `lang_index`,`name`)
VALUES
(1,'ru','Нью Йорк'),
(1,'en','New York'),
(2,'en','Boston'),
(2,'ch','波士顿')
;
Logic of search.
If row with lang_index='ru' AND id IN(1,2) found. it must return all with lang_index='ru'
If one or more rows with lang_index='ru' not exists But exists with lang_index='en' and with some id.
Then it must return all exists with land_index='ru' AND id IN(1,2) and all that not found with lang_index='ru' but found with lang_index='en' (in table - all rows with lang_index='en' always exists)
See on sqlfiddle
I need only one result per id. I tried GROUP BY id but its not works correctly.
Output must be
1,'ru','Нью Йорк'
2,'en','Boston' (because lang_index='ru' with id 2 not found)
SELECT
coalesce(max(CASE WHEN lang_index='ru' THEN name ELSE null END), name) as name
FROM
location_areas_localized
WHERE
id IN (1,2)
AND (lang_index='en' OR lang_index='ru')
group by
id
ORDER BY
FIELD(lang_index,'ru','en');
Without using aggregation functions, it only takes the first matching row. The subquery with ORDER BY enforce the fact that for the same id either the "ru" (or "en", if "ru" is not present) row is the first one.
SELECT *
FROM(
SELECT *
FROM location_areas_localized
ORDER BY FIELD(lang_index,'ru','en','ch')
) as inv
WHERE id IN (1,2)
GROUP BY id
See SQLFiddle example