MySQL, create view from columns from same table - mysql

I have this table:
CREATE TABLE one (
id bigint(11) primary key,
email varchar(100),
refer_link varchar(8),
referrer varchar (8)
);
When users submit forms they get a unique refer link (refer_link). When another user submit forms with that link in his referrer column is inserted that refer link.
So in example I will have this table:
id email refer_link referrer
---------------------------------------------------------
1 jerry#jerry.com ref11111
2 elaine#elaine.com ref22222 ref11111
3 george#george.com ref33333 ref22222
4 kramer#kramer.com ref44444 ref11111
5 cosmo#cosmo.com ref55555 ref44444
How to create this view?
email refer_email refer_count
--------------------------------------------------------
jerry#jerry.com 2
elaine#elaine.com jerry#jerry.com 1
george#george.com elaine#elaine.com 0
kramer#kramer.com jerry#jerry.com 1
cosmo#cosmo.com kramer#kramer.com 0
Thank you very much for help!

Try the below sub query,
$query = "select o.email,
IFNULL( (select email from one where o.referrer = refer_link ),'') as refer_email,
(select count(referrer) from one where referrer = o.refer_link ) as refer_count
from one as o order by id ";

DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,email VARCHAR(50) NOT NULL
,referrer INT NULL
);
INSERT INTO my_table VALUES
(1,'jerry#jerry.com',NULL),
(2,'elaine#elaine.com',1),
(3,'george#george.com',2),
(4,'kramer#kramer.com',1),
(5,'cosmo#cosmo.com',4);
SELECT x.*, COUNT(y.id) refer_count FROM my_table x LEFT JOIN my_table y ON y.referrer = x.id GROUP BY x.id;
+----+-------------------+----------+-------------+
| id | email | referrer | refer_count |
+----+-------------------+----------+-------------+
| 1 | jerry#jerry.com | NULL | 2 |
| 2 | elaine#elaine.com | 1 | 1 |
| 3 | george#george.com | 2 | 0 |
| 4 | kramer#kramer.com | 1 | 1 |
| 5 | cosmo#cosmo.com | 4 | 0 |
+----+-------------------+----------+-------------+

Related

How to join tables based on ids and names with multiple values

I have 3 mysql tables:
Users:
id | name | interest | user_id
1 | user1 | 1,2 | 1
2 | user2 | 1,2,3 | 2
Interests:
id | name
1 | interest1
2 | interest2
User_posts:
id | user_id | desc
1 | 23 | something..
2 | 31 | something..
What i want to achieve is i want join interest column from users table into user_posts table based on user_id with user_name from interests table which i have already done using this query:
select user_posts.*, users.interest as interest_ids, zaya.interests.name as interest_name
from user_posts
left join users ON user_posts.id = users.interest
left join interests ON user_posts.id = users.interest;
i get the following output with this query:
User_posts:
id | user_id | desc | interest_ids | interest_name
1 | 23 | something.. | 1,2 | interest1
2 | 31 | something.. | 1,2,3 | interest1
Output i want to achieve:
User_posts:
id | user_id | desc | interest_ids | interest_name
1 | 23 | something.. | 1,2 | interest1, interest2
2 | 31 | something.. | 1,2,3 | interest1, interest2, interest3
I believe this can be solved using the temporary table creation method and have tried solving this but i'm newbie in mysql queries and getting errors please help me with the correct query.
Thank you in advance.
I would use a sub query rather than a join if you're looking to just get back one col form the [interests] table.
Here is an example using STRING_SPLIT function to get the names :
DECLARE #users TABLE(
[ID] int IDENTITY(1,1)
,[NAME] varchar(32)
,[INTERESTS] varchar(32)
)
INSERT INTO #users
VALUES ('user1', '1,2'), ('user2', '1,2,3')
DECLARE #interests TABLE(
[ID] int IDENTITY(1,1)
,[NAME] varchar(32)
)
INSERT INTO #interests
VALUES ('interests1'), ('interests2'), ('interests3')
DECLARE #user_posts TABLE(
[ID] int IDENTITY(1,1)
,[USERID] int
,[DESC] varchar(32)
)
INSERT INTO #user_posts
VALUES (1, 'post1'), (2, 'post2')
SELECT
U.[ID]
,UP.[USERID]
,UP.[DESC]
,U.[INTERESTS]
,SUBSTRING((SELECT ',' + I2.[NAME]
FROM #interests I2
WHERE I2.[ID] IN (SELECT [name] FROM STRING_SPLIT(U.[INTERESTS], ','))
FOR XML PATH('')), 2, 1000) AS 'INTEREST_NAME'
FROM #user_posts UP
LEFT JOIN #users U
ON U.[ID] = UP.[USERID]
This should return :
ID
USERID
DESC
INTERESTS
INTEREST_NAME
1
1
post1
1,2
interests1,interests2
2
2
post2
1,2,3
interests1,interests2,interests3

MySQL Delete with Join and Count

I have two tables s_filter_values and s_filter_articles.
s_filter_values: s_filter_articles:
| id | value | | articleID | valueID |
|----|-------| |-----------|---------|
| 1 | one | | 1 | 2 |
| 2 | two | | 1 | 3 |
| 3 | three | | 2 | 2 |
With the following statement I count the the occurence of the values
respectively I get the values that are not linked to an article:
SELECT v.*, IFNULL(COUNT(a.articleID), 0) AS counter
FROM s_filter_values AS v
LEFT JOIN s_filter_articles AS a ON v.id = a.valueID
GROUP BY v.id
HAVING counter = 0
In this case, I got
| id | value | counter |
| 1 | one | 0 |
My questions is: How can I use this statement to delete all rows from s_filter_values that are not linked to an article?
I will suggest using NOT EXIST rather than NOT IN.
The NOT EXISTS should perform faster on a large dataset.
There is one key difference between the two constructs: if the subquery returns a NULL in its results then the NOT IN condition will fail, because null is neither equal-to nor not-equal-to any other value.
create table s_filter_values(
id int(10),
`value` varchar(10) );
insert into s_filter_values values ( 1,'one'),( 2,'two'),( 3,'three');
create table s_filter_articles(
articleID int(10),
valueID int(10) );
insert into s_filter_articles values ( 1,2),( 1,3),( 2,2);
DELETE FROM s_filter_values
WHERE NOT EXISTS (SELECT valueID FROM s_filter_articles a where a.valueID= s_filter_values.id);
Demo: https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/84
I would use a subquery to get all IDs that are in the table. Then drop the rows from s_filter_values that are not present.
DELETE FROM s_filter_values WHERE id NOT IN (SELECT DISTINCT valueID FROM s_filter_articles);
A simple sub select should do it:
DELETE FROM `s_filter_values`
WHERE `id` NOT IN SELECT DISTINCT `valueID` FROM `s_filter_articles`

Select locations where the user doesn't have it bound yet from 3 tables

I have 3 tables
User Info
id
name
1
bob
2
jane
3
tom
Locations
id
name
1
Test1
2
Test2
3
Test3
4
Test4
User Locations
userID
locationID
1
1
1
2
2
3
Basically What I am trying to achieve is to pull the location names where the user doesn't have it bound already.
In the above list Bob has 2 locations bounded "test 1" and "test 2" but he doesn't have "test 3" or "test 4" yet. I Only want the data to return test 3 and 4 since those are the only ones Bob doesn't have.
For Jane She only has Test 3 bounded but none of the remaining 3
Originally I had tried this and it somewhat worked. However Every time another user gets an unbounded location the its removed from the list. I'm not sure how I would add the user ID in all this so it's only specific to that user.
SELECT `name` FROM `locations`
WHERE `id` NOT IN (SELECT `locationID` FROM `user_locations`)
Create a cartesain product of the user and locations table (cross join), then using an outer join allows us to find rows that are as yet unmatched in user_locations:
select
user_info.ID AS UserID
, locations.ID AS locationID
from user_info
cross join locations
left outer join user_locations on user_info.id = user_locations.userid
and locations.id = user_locations.locationid
where user_locations.userid IS NULL
and user_info.name = 'bob'
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE user_info(
id INTEGER NOT NULL PRIMARY KEY
,name VARCHAR(4) NOT NULL
);
INSERT INTO user_info(id,name) VALUES (1,'bob');
INSERT INTO user_info(id,name) VALUES (2,'jane');
INSERT INTO user_info(id,name) VALUES (3,'tom');
CREATE TABLE locations(
id INTEGER NOT NULL PRIMARY KEY
,name VARCHAR(5) NOT NULL
);
INSERT INTO locations(id,name) VALUES (1,'Test1');
INSERT INTO locations(id,name) VALUES (2,'Test2');
INSERT INTO locations(id,name) VALUES (3,'Test3');
INSERT INTO locations(id,name) VALUES (4,'Test4');
CREATE TABLE user_locations(
userID INTEGER NOT NULL
,locationID INTEGER NOT NULL
);
INSERT INTO user_locations(userID,locationID) VALUES (1,1);
INSERT INTO user_locations(userID,locationID) VALUES (1,2);
INSERT INTO user_locations(userID,locationID) VALUES (2,3);
Query 1:
select
user_info.ID AS UserID
, locations.ID AS locationID
from user_info
cross join locations
left outer join user_locations on user_info.id = user_locations.userid
and locations.id = user_locations.locationid
where user_locations.userid IS NULL
order by 1,2
Results:
| UserID | locationID |
|--------|------------|
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
| 2 | 2 |
| 2 | 4 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |

phpmyadmin update m to n relationship table to remove duplicates from separate table

I have 2 tables.
CREATE TABLE designs
( game_id INT NOT NULL,
des_id INT NOT NULL,
PRIMARY KEY(game_id, des_id),
FOREIGN KEY(game_id) REFERENCES Game(id),
ON UPDATE CASCADE)
CREATE TABLE designer
( name VARCHAR(30) NOT NULL,
id INT NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY(id) REFERENCES designs(des_id),
ON UPDATE CASCADE);
Lets say I have data:
designs:
0---0
0---1
1---2
2---3
2---4
.............................
designer:
Bob---0
Jill---1
Bob---2
Rob---3
Jill---4
After the update, I would like the "designs" table to look like:
0---0
0---1
1---0
2---3
2---1
What update query would I need to accomplish this?
Some queries I tried are:
UPDATE designs
SET des_id = (
SELECT a.id
FROM designer as a
JOIN designer as b
ON a.name=b.name AND a.id < b.id
WHERE des_id = b.id);
...
UPDATE `designs` as a
JOIN designer as b
ON a.des_id=b.id
SET a.des_id = b.id
WHERE b.id = (
SELECT c.id
FROM designer as c
LEFT JOIN designer as d
ON c.name=d.name
WHERE c.id<d.id)
Here's one idea. Note that it uses an documented hack in the form of a 'group by/order by' trick:
UPDATE designs d
JOIN
( select d1.id matcher_id
, d2.id select_id
from `designer` d1
JOIN designer d2
ON d1.name = d2.name
group
by d1.id
Order
by d2.id
) x
ON x.matcher_id = d.des_id
SET d.des_id = select_id
Your LEFT JOIN idea is almost right, but here's another idea which is faster...
DROP TABLE IF EXISTS designs;
CREATE TABLE designs
( game_id INT NOT NULL
, designer_id INT NOT NULL
, PRIMARY KEY(game_id, designer_id)
);
DROP TABLE IF EXISTS designers;
CREATE TABLE designers
( name VARCHAR(30) NOT NULL
, designer_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
INSERT INTO designs VALUES
(1,1),
(1,2),
(2,3),
(3,4),
(3,5);
INSERT INTO designers VALUES
('Bob',1),
('Jill',2),
('Bob',3),
('Rob',4),
('Jill',5);
SELECT * FROM designs;
+---------+-------------+
| game_id | designer_id |
+---------+-------------+
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 3 | 5 |
+---------+-------------+
SELECT * FROM designers;
+------+-------------+
| name | designer_id |
+------+-------------+
| Bob | 1 |
| Jill | 2 |
| Bob | 3 |
| Rob | 4 |
| Jill | 5 |
+------+-------------+
UPDATE designs g
JOIN designers d
ON d.designer_id = g.designer_id
JOIN designers x ON x.name = d.name
JOIN
( SELECT name
, MIN(designer_id) min_designer_id
FROM designers
GROUP
BY name
) y
ON y.name = x.name
AND y.min_designer_id = x.designer_id
SET g.designer_id = x.designer_id;
SELECT * FROM designs;
+---------+-------------+
| game_id | designer_id |
+---------+-------------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 3 | 2 |
| 3 | 4 |
+---------+-------------+
Actually, in the special case of an UPDATE, I think this will work just as well, and I'm not really sure that it's any less performative...
UPDATE designs g
JOIN designers x
ON x.designer_id = g.designer_id
JOIN designers y
ON y.name = x.name
AND y.designer_id < x.designer_id
SET g.designer_id = y.designer_id;

SQL query composition search by 4 tables

I have a problem with a SQL query (i am using MySQL)
I got some tables, which have to find an output where they have to be multiplied.
First table lipid:
ID | name | mass | hg |
1 | PC 32:2 | 700 | PC |
2 | PC 32:1 | 800 | PC |
Second table FA:
ID | name | mass
1 | FA 16:1 | 300
2 | FA 16:0 | 400
3 | FA 16:2 | 200
a
Third table Cat:
ID | name | snpos | backbone | LC
1 | gpl | 2 | 25 | 1
Fourth table LC:
ID | name | mass
1 | PC | 75
I need a SQL query that can give me a result where i use something from all 4 tables.
I will need a result which can give me which composition of FA´s (table 2) that can give me the correct input lipid (table 1).
So i will input hg = PC and mass = 700. By this information it should give me which FA composition it could be.
From table 3 cat, it should use the snpos information to find out how many FA it should find in this case 2, and the backbone should be added to the result same as the mass from table 4 LC, else it will never get to the mass of input.
It would look something like:
FA 16:1 FA 16:1 (mass 600) + PC (mass 75) + backbone (25) = 700
This isn't intended as a definitive solution, nor even an advocation of the method; just a demonstration of principle...
DROP TABLE IF EXISTS lipid;
CREATE TABLE lipid
(ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(12) NOT NULL UNIQUE
,mass INT NOT NULL
,hg CHAR(2) NOT NULL
);
INSERT INTO lipid VALUES
(1 ,'PC 32:2',700,'PC'),(2,'PC 32:1',800,'PC');
DROP TABLE IF EXISTS FA;
CREATE TABLE FA
(ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(12) NOT NULL
,mass INT NOT NULL
);
INSERT INTO fa VALUES
(1 ,'FA 16:1',300),
(2 ,'FA 16:0',400),
(3 ,'FA 16:2',200);
DROP TABLE IF EXISTS Cat;
CREATE TABLE Cat
(ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(12) NOT NULL
,snpos TINYINT NOT NULL
,backbone INT NOT NULL
,LC INT NOT NULL
);
INSERT INTO Cat VALUES
(1 ,'gpl',2,25,1);
DROP TABLE IF EXISTS LC;
CREATE TABLE LC
(ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name CHAR(2) NOT NULL
,mass INT NOT NULL
);
INSERT INTO LC VALUES (1,'PC',75);
SELECT l.id lipid_id
, l.name lipid_name
, l.mass lipid_mass
, l.hg
, fa.*
, c.id cat_id
, c.name cat_name
, c.snpos snpos
FROM lipid l
JOIN lc
ON lc.name = l.hg
JOIN cat c
ON c.lc = lc.id
JOIN
( SELECT 3 snpos,x.name name_x,x.mass mass_x,y.name name_y,y.mass mass_y,z.name name_z,z.mass mass_z, x.mass+y.mass+z.mass total FROM fa x JOIN fa y ON y.id < x.id JOIN fa z ON z.id < y.id
UNION
SELECT 2 ,x.name, x.mass,y.name,y.mass,NULL,0, x.mass+y.mass FROM fa x JOIN fa y ON y.id < x.id
UNION
SELECT 1,name,mass,NULL,0,NULL,0, mass FROM fa
) fa
ON fa.snpos = c.snpos
AND fa.total = 700-c.backbone-lc.mass
WHERE l.mass = 700
AND l.hg = 'PC';
+----------+------------+------------+----+-------+---------+--------+---------+--------+--------+--------+-------+--------+----------+-------+
| lipid_id | lipid_name | lipid_mass | hg | snpos | name_x | mass_x | name_y | mass_y | name_z | mass_z | total | cat_id | cat_name | snpos |
+----------+------------+------------+----+-------+---------+--------+---------+--------+--------+--------+-------+--------+----------+-------+
| 1 | PC 32:2 | 700 | PC | 2 | FA 16:2 | 200 | FA 16:0 | 400 | NULL | 0 | 600 | 1 | gpl | 2 |
+----------+------------+------------+----+-------+---------+--------+---------+--------+--------+--------+-------+--------+----------+-------+