Inserting data from a join within tables - mysql

I'm trying to figure out how to extend a table of company_ids using a group reference from another table. For a given company_name, I want to get its company_ids, join them with the company_groups table, and get their group_ids. From there, I want to get every company_id associated with the group_id, and insert them in the companies table with the proper company_name.
The structure is a bit atypical. A single company name can have many IDs, because the ID isn't used as a unique identifier for a single company. I'm trying to make sure all of them get copied to the companies table. I'm sure there's a fairly simple join command, but I've never been very good at joining tables within themselves. Can anyone help? Thanks!
+---------------+
| companies |
+---------------+
| company_id PK |
| company_name |
+---------------+
+----------------+
| company_groups |
+----------------+
| company_id PK |
| group_id |
+----------------+
Here's an example. In the companies table, I have the company "Tesla", with three different IDs.
+--------------+------------+
| company_name | company_id |
+--------------+------------+
| Tesla | 647552 |
| Tesla | 927572 |
| Tesla | 748563 |
+--------------+------------+
In the company_groups table, each group_id has one or more company_ids.
+----------+------------+
| group_id | company_id |
+----------+------------+
| 227 | 647552 |
| 227 | 111743 |
| 227 | 111842 |
+----------+------------+
I want to match the company_name to multiple group_ids, then find all company_ids associated with the group. The new company_ids would then be inserted in the companies table like this:
+--------------+------------+
| company_name | company_id |
+--------------+------------+
| Tesla | 647552 |
| Tesla | 927572 |
| Tesla | 748563 |
| Tesla | 111743 |
| Tesla | 111842 |
+--------------+------------+

You cannot insert into a table when the same table name appear in the where clause.
You can use a temporary third table to do this job
At second thought, your question is either funny or not clear enough, please provide your sample data, so that i can update my answer

I figured it out. A nested query works well:
REPLACE INTO companies (company_name, company_id)
SELECT a.company_name, company_groups.company_id
FROM
(
SELECT group_id, company_groups.company_id, companies.company_name
FROM companies
JOIN company_groups
ON companies.company_id=company_groups.company_id
GROUP BY group_id
) a
JOIN company_groups
ON company_groups.group_id=a.group_id
GROUP BY company_id;

Related

Mysql - Compare int field with comma separated field from another table

I have two tables in a MySQL database like this:
User:
userid |userid | Username | Plan(VARCHAR) | Status |
-----------+------------+--------------+---------------+---------+
1 | 1 | John | 1,2,3 |1 |
2 | 2 | Cynthia | 1,2 |1 |
3 | 3 | Charles | 2,3,4 |1 |
Plan: (planid is primary key)
planid(INT) | Plan_Name | Cost | status |
-------------+----------------+----------+--------------+
1 | Tamil Pack | 100 | ACTIVE |
2 | English Pack | 100 | ACTIVE |
3 | SportsPack | 100 | ACTIVE |
4 | KidsPack | 100 | ACTIVE |
OUTPUT
id |userid | Username | Plan | Planname |
---+-------+----------+------------+-------------------------------------+
1 | 1 | John | 1,2,3 |Tamil Pack,English Pack,SportsPack |
2 | 2 | Cynthia | 1,2 |Tamil Pack,English Pack |
3 | 3 | Charles | 2,3,4 |English Pack,Sportspack, Kidspack |
Since plan id in Plan table is integer and the user can hold many plans, its stored as comma separated as varchar, so when i try with IN condition its not working.
SELECT * FROM plan WHERE find_in_set(plan_id,(select user.planid from user where user.userid=1))
This get me the 3 rows from plan table but i want the desired output as above.
How to do that.? any help Please
A rewrite off your query what should work is as follows..
Query
SELECT
all columns you need
, GROUP_CONCAT(Plan.Plan_Name ORDER BY Plan.planid) AS Planname
FROM
Plan
WHERE
FIND_IN_SET(Plan.plan_id,(
SELECT
User.Plan
FROM
user
WHERE User.userid = 1
)
)
GROUP BY
all columns what are in the select (NOT the GROUP_CONCAT function)
You also can use FIND_IN_SET on the ON clause off a INNER JOIN.
One problem is that the join won't ever use indexes.
Query
SELECT
all columns you need
, GROUP_CONCAT(Plan.Plan_Name ORDER BY Plan.planid) AS Planname
FROM
User
INNER JOIN
Plan
ON
FIND_IN_SET(Plan.id, User.Plan)
WHERE
User.id = 1
GROUP BY
all columns what are in the select (NOT the GROUP_CONCAT function)
Like i said in the comments you should normalize the table structures and add the table User_Plan whats holds the relations between the table User and Plan.

Retrieve all not logged in users from mysql tables (SQL query)

I have 2 tables listed below:
+-------------+-----------+--------------+-------------------------------+
| v3_customer |
+-------------+-----------+--------------+-------------------------------+
| customer_id | firstname | lastname | email |
+-------------+-----------+--------------+-------------------------------+
| 1 | Piet | Pizza | piet.pizza#example.com |
| 2 | Klaas | Hein | klaas.hein#example.com |
| 3 | Henk | Crowdcontrol | henk.crowdcontrol#example.com |
+-------------+-----------+--------------+-------------------------------+
+-------------+-------------+---------------+
| v3_customer_activity |
+-------------+-------------+---------------+
| activity_id | customer_id | key |
+-------------+-------------+---------------+
| 1 | 1 | login |
| 2 | 1 | order_account |
| 3 | 2 | login |
+-------------+-------------+---------------+
What i want is to select all customers which haven't logged in yet (note the login key in v3_customer_activity). So in this case that would be the customer with customer_id: 3
I'm using a mysql database.
I have tried using the following query:
SELECT DISTINCT v3_customer.customer_id, v3_customer.firstname, v3_customer.lastname, v3_customer.email FROM `v3_customer` JOIN v3_customer_activity ON v3_customer.customer_id = v3_customer_activity.customer_id WHERE v3_customer.customer_id != (SELECT v3_customer_activity.customer_id FROM v3_customer_activity)
In the hope it would iterate between the rows found in the subquery.
This resulted in an error telling me a subquery may not contain multiple rows.
TL;DR
What I want is to retrieve every customer from v3_customer who is not listed in the table v3_customer_activity
Try this:
select v3_customer.* from v3_customer
left join v3_customer_activity on v3_customer.customer_id=v3_customer_activity.customer_id
where v3_customer_activity.customer_id is null;
Left join v3_customer table with v3_customer_activity and filter records which are not matched.
select v3_customer.* from v3_customer
where v3_customer.customer_id not in (SELECT v3_customer_activity.customer_id FROM v3_customer_activity)

Join multiple tables with same column name

I have these tables in my MySQL database:
General table:
+----generalTable-----+
+---------------------+
| id | scenario | ... |
+----+----------+-----+
| 1 | facebook | ... |
| 2 | chief | ... |
| 3 | facebook | ... |
| 4 | chief | ... |
Facebook Table:
+----facebookTable-----+
+----------------------+
| id | expiresAt | ... |
+----+-----------+-----+
| 1 | 12345678 | ... |
| 3 | 45832458 | ... |
Chief Table:
+------chiefTable------+
+----------------------+
| id | expiresAt | ... |
+----+-----------+-----+
| 2 | 43547343 | ... |
| 4 | 23443355 | ... |
Basically, the general table holds some (obviously) general data. Based on the generalTable.scenario you can look up more details in the other two tables, which are in some columns familiar (expiresAt for example) but in others not.
My question is, how to get the joined data of generalTable and the right detailed table in just one query.
So, I would like a query like this:
SELECT id, scenario, expiresAt
FROM generalTable
JOIN facebookTable
ON generalTable.id = facebookTable.id
JOIN chiefTable
ON generalTable.id = chiefTable.id
And an output like this:
| id | scenario | expiresAt |
+----+----------+-----------+
| 1 | facebook | 12345678 |
| 2 | chief | 43547343 |
| 3 | facebook | 45832458 |
| 4 | chief | 23443355 |
However, this doesn't work, because both facebookTable and chiefTable have ambiguous column name "expiresAt". For the ease of use I want to keep it that way. The result table should also only have one column "expiresAt" that is automatically filled with the right values from either facebookTable or chiefTable.
You might want to consider adding expiredAt to your general table, and removing it from the others, to remove duplication in the schema, and to make this particular query simpler.
If you need to stick with your current schema, you can use table aliases to resolve the name ambiguity, and use two joins and a union to create the result you are looking for:
SELECT g.id, g.scenario, f.expiresAt
FROM generalTable g
JOIN facebookTable f
ON g.id = f.id
UNION ALL
SELECT g.id, g.scenario, c.expiresAt
FROM generalTable g
JOIN chiefTable c
ON g.id = c.id;
The outer join approach mentioned in another answer would also solve the problem.
One way you could accomplish it is with LEFT JOIN. In the result fields you can do something like this for common fields IF(fTbl.id IS NULL, cTbl.expiresAt, fTbl.expiresAt) AS expiresAt.

How can I show the counts of distinct values and include zeros?

I have a simple MySQL DB with the following fields:
mysql> SELECT * from table;
+----+-----------+------+
| id | location | name |
+----+-----------+------+
| 1 | NJ | Gary |
| 2 | MN | Paul |
| 3 | AZ | |
| 4 | MI | Adam |
| 5 | NJ | |
| 6 | MN | Dave |
+----+-----------+------+
6 rows in set (0.00 sec)
I need to retrieve a list of how many people are from each state, excluding those who don't have a name. In other words, I'm trying to reproduce the following result:
+----------+-------+
| location | count |
+----------+-------+
| AZ | 0 |
| MI | 1 |
| MN | 2 |
| NJ | 1 |
+----------+-------+
I'm able to get close with
SELECT location, COUNT(*) AS count FROM table WHERE name!='' GROUP BY location;
However, COUNT(*) excludes the zero counts. I attempted to use JOIN along with the table produced by
SELECT DISTINCT location, null as count from table;
but a LEFT JOIN throws out the count column from the right table, and a RIGHT JOIN doesn't seem to include the zero rows or the actual counts for some reason.
I feel as though there's a MySQL command or something simple that I'm missing. I just need to find a way to merge the two tables based on location.
Can anybody point me in the right direction?
COUNT will return number of non-null values, so you need a way to convert empty strings to nulls to get 0s.
SELECT location, COUNT(NULLIF(name,'')) AS count FROM table GROUP BY location;

retrieving data from two mysql tables where the second table depends on the first

I have two MySql tables:
users(id_user, name, age, gender ).
ways(#id_user,id_way, start, end, date).
What I want is to retrieve all the ways with their corresponding users details.
So my result would be like this:
id_way | start | end | date | id_user | name | age | gender
---------------------------------------------------------------------------
2 | place1 | place2 | 12/06/2013 | 145 | john | 28 | m
Have you tried JOIN?
SELECT ways.id_way, ways.start, ways.end, ways.date, users.*
FROM ways JOIN users USING (id_user)