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')
Related
I'm new to MySQL and trying to select the total number of orders for each user in the orders table. Also, I'm trying to order the results by most orders to the least orders.
This is what I have for order table
CREATE TABLE `order` (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
created TIMESTAMP NOT NULL DEFAULT NOW(),
user_id INTEGER NOT NULL,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE RESTRICT
);
And this is what I have for user table
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) NOT NULL UNIQUE,
`password` VARCHAR(255) NOT NULL,
first_name VARCHAR(255),
last_name VARCHAR(255),
created TIMESTAMP NOT NULL DEFAULT NOW()
);
I have referenced other resources and tried the following, but I'm getting an error..Not sure how I can go about it?
SELECT COUNT(DISTINCT order_id) AS user_id
FROM `order`
GROUP BY user_id
this will
group by user_id
then count all lines
you will get one line per user_id with the count
ps: distinct is useless because order.id is an autoincrement key.
select user_id, count(*) as nb
from order
group by user_id
Or this if you want users with no orders included.
you need to start from user table, join all related orders, and basically do the same counting and grouping as before.
select u.id, count(*) as nb
from user as u
left join `order` as o on o.user_id = u.id
group by u.id
I am implementing a simple follow/followers system in MySQL. So far I have three tables that look like:
CREATE TABLE IF NOT EXISTS `User` (
`user_id` INT AUTO_INCREMENT PRIMARY KEY,
`username` varchar(40) NOT NULL ,
`pswd` varchar(255) NOT NULL,,
`email` varchar(255) NOT NULL ,
`first_name` varchar(40) NOT NULL ,
`last_name` varchar(40) NOT NULL,
CONSTRAINT uc_username_email UNIQUE (username , email)
);
-- Using a middle table for users to follow others on a many-to-many base
CREATE TABLE Following (
follower_id INT(6) NOT NULL,
following_id INT(6) NOT NULL,
KEY (`follower_id`),
KEY (`following_id`)
)
CREATE TABLE IF NOT EXISTS `Tweet` (
`tweet_id` INT AUTO_INCREMENT PRIMARY KEY,
`text` varchar(280) NOT NULL ,
-- I chose varchar vs TEXT as the latter is not stored in the database server’s memory.
-- By querying text data MySQL has to read from it from the disk, much slower in comparison with VARCHAR.
`publication_date` DATETIME NOT NULL,,
`username` varchar(40),
FOREIGN KEY (`username`) REFERENCES `user`(`username`)
ON DELETE CASCADE
);
Lets say I want to write a query that returns the 10 latest tweets by users followed by the user with username "Tom". What is the best way to writhe that query and return results with username, first name, last name, text and publication date.
Also if one minute later I want to query again 10 latest tweets and assuming someone Tom follows tweets during that minute, how do I query the database to not select tweets that have already shown in the first query?
To answer your first question:
SELECT u1.username, u1.first_name, u1.last_name, t.text, t.publication_date
FROM Tweet t
JOIN User u1 ON t.username = u1.username
JOIN Following f ON f.following_id = u1.user_id
JOIN User u2 ON u2.user_id = f.follower_id
WHERE u2.username = 'Tom'
ORDER BY t.publication_date DESC
LIMIT 10
For the second part, simply take the tweet_id from the first row of the first query (so the latest tweet_id value) and use it in the WHERE clause for the next query i.e.
WHERE u2.username = 'Tom'
AND t.tweet_id > <value from previous query>
To get latest 10 tweets for Tom:
select flg.username, flg.first_name, flg.last_name, t.tweet_id, t.text, t.publication_date
from user flr
inner join following f on f.follower_id = flr.user_id
inner join user flg on flg.user_id = f.following_id
inner join tweet t on t.username = flg.username
where flr.username = 'Tom'
order by tweet_id desc
limit 10
To get the next 10 tweets, pass in the max tweet_id, and apply an additional condition in the where clause:
where flr.username = 'Tom'
and t.tweet_id > <previous_max_tweet_id>
I wrote an example to describe my problem in a more complex database.
I use MySQL 5.7 with Delphi XE8.
I have 2 tables:
CREATE TABLE customers
(ID INT NOT NULL AUTO_INCREMENT ,
Name VARCHAR(30) NOT NULL ,
PRIMARY KEY (ID)
) ENGINE = InnoDB;
CREATE TABLE orders
(IDorders INT NOT NULL AUTO_INCREMENT ,
customerID INT NOT NULL ,
Description VARCHAR(30) NOT NULL ,
DateOrder Date NOT NULL ,
PRIMARY KEY (IDorders),
INDEX DateOrderIndex (DateOrder, customerID) USING BTREE;
) ENGINE = InnoDB;
select *,
(SELECT MAX(DateOrder) FROM Orders WHERE Orders.customerID =
customers.ID) as LastOrder
FROM customers
My problem is:
the customer table has 58,000 records
and
the orders table has 200,000 records
The query result occurs after 28 seconds.
Where am I doing wrong?
You can try to use JOIN with MAX and GROUP BY in subquery.
select c.*,
t1.maxDt
FROM customers c
JOIN (
SELECT customerID,MAX(DateOrder) maxDt
FROM Orders
GROUP BY customerID
) t1 on t1.customerID = c.ID
Note
if your query is slow you can try to create indexs on Orders.customerID and
customers.ID
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);
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