Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have a table:
| staff_id | leader_id | team_role | importance |
+ + + + +
| 1001037 | 1000321 | HOD | 1 |
| 1001037 | 1000322 | HOD | 1 |
| 1001037 | 1001037 | Supervisor | 2 |
| 1001094 | 1001037 | Checker | 3 |
| 1001075 | 1001037 | Checker | 3 |
| 1001096 | 1001075 | Squad Leader | 4 |
| 1000393 | 1001094 | Squad Leader | 4 |
| 1000465 | 1001094 | Squad Leader | 4 |
| 1000585 | 1001075 | Squad Leader | 4 |
| 1000664 | 1000585 | Team Member | 5 |
| 1000583 | 1000585 | Team Member | 5 |
| 1000570 | 1000465 | Team Member | 5 |
| 1000316 | 1000465 | Team Member | 5 |
In php it look like this:
If I want to remove user with staff_id = 1001075 I need to remove all assigned to this user ids. So it will be ids where 1001075 is leader_id. I am able to this but I also need to remove users going down to the tree so where leader_id= 1001075 is will be 1000585 Then I need to remove users where leader_id= 1000585
In the end I need to delete these users with staff_id:
1001075
1001096
1000585
1000664
1000583
How can I do that?
There are two ways to do this:
Recursively query for all the ids to find out all the children and delete the rows one by one. Have a look at this answer for approaches to recursively query the ids.
Run an ALTER TABLE script and make leader_id a foreign key, referencing to staff_id of the same table, and define with ON DELETE CASCADE. By this way, when you delete a leader row, it will delete all the subsequent rows, e.g.:
ALTER TABLE table
ADD CONSTRAINT fk_leader_id FOREIGN KEY (leader_id) REFERENCES table(staff_id) ON DELETE CASCADE;
I would prefer the second approach.
Related
I have a small database:
+-----------+-----------+------------------------+
| Name | Number | Hobby |
+-----------+-----------+------------------------+
| Alex | 2, 3 | Game, Shopping |
+-----------+------------------------------------+
It's mean Number 2 is Game and Number 3 is Shopping.
How can I show above data like this table
+-----------+-----------+
| 2 | Game |
+-----------+-----------+
| 3 | Shopping |
+-----------+------------
Your database is not normalized. You need a third table that will be what's usually called a join table.
The people table. The primary key is id
+-----------+-----------+
| Id | Name |
+-----------+-----------+
| 1 | Alex |
| 2 | Thor |
| 3 | Iron Man |
| 4 | Dr Stange |
| 5 | Thanos |
+-----------+------------
The hobbies Table
+-----------+-----------+
| Id | Name |
+-----------+-----------+
| 1 | Game |
| 2 | Shopping |
| 3 | Fighting |
+-----------+-----------+
Join table called (for example) people_hobbies
+-----------+-----------+
| person_id | hobby_id |
+-----------+-----------+
| 1 | 1 |
| 1 | 2 |
+-----------+-----------+
This people_hobbies table will use person_id and hobby_id to create a multi field primary key. This will ensure that you will not be able to add the same combination twice... which should not even make sense.
person_id is a foreign key that references the id from the people table.
hobby_id is a foreign key that references the id from the hobbies table.
Having foreign keys will let you avoid having a key in the people_hobbies table that do not exist in both the people and the hobbies table.
The example in the table below shows that the person id 1 has two hobbies (1 and 2). For a human, that translates to Alex's hobbies are Game and Shopping.
The above structure will let you manage your DB the way most people do.
Just keep a few things in mind:
You cannot add anything in people_hobbies before they exist in both people and hobbies tables
You must have the CASCADE UPDATE and CASCADE DELETE to the foreign key definitions so that when you delete a person or a hobby from your tables, it will remove the relationship from the people_hobbies table.
SELECT * FROM ints;
+---+
| i |
+---+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+---+
SELECT * FROM bad_schema;
+------+--------+----------------+
| name | number | hobby |
+------+--------+----------------+
| Alex | 2, 3 | Game, Shopping |
+------+--------+----------------+
CREATE TABLE better_schema AS
SELECT DISTINCT name
, SUBSTRING_INDEX(SUBSTRING_INDEX(number,',',i+1),',',-1) + 0 number
, TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(hobby,',',i+1),',',-1)) hobby
FROM bad_schema
, ints;
SELECT * FROM better_schema;
+------+--------+----------+
| name | number | hobby |
+------+--------+----------+
| Alex | 2 | Game |
| Alex | 3 | Shopping |
+------+--------+----------+
A table contains the following data, is using INNODB, has a UNIQUE constraint on position/fk, and doesn't allow NULL for position.
+----+----------+-----+
| id | position | fk |
+----+----------+-----+
| 1 | 1 | 123 |
| 2 | 2 | 123 |
| 3 | 3 | 123 |
| 4 | 4 | 123 |
| 5 | 5 | 123 |
| 6 | 6 | 123 |
| 7 | 7 | 123 |
| 8 | 8 | 123 |
| 9 | 9 | 123 |
| 10 | 10 | 123 |
+----+----------+-----+
PHP receives a request to update the table to the following. The format of the request can be provided how ever is most convenient such as [2,1,4,3,6,5,8,7,10,9] or [{"id":1, "position":2}, ... ], etc.
+----+----------+-----+
| id | position | fk |
+----+----------+-----+
| 1 | 2 | 123 |
| 2 | 1 | 123 |
| 3 | 4 | 123 |
| 4 | 3 | 123 |
| 5 | 6 | 123 |
| 6 | 5 | 123 |
| 7 | 8 | 123 |
| 8 | 7 | 123 |
| 9 | 10 | 123 |
| 10 | 9 | 123 |
+----+----------+-----+
I've confirmed that SET unique_checks=0; will not allow unique checks to be temporarily disabled, and don't wish to actually remove the unique index, update the table, and reapply the unique index.
How can this table be updated?
If there is no simple means to do so, I thought of a couple of options, but don't like them:
Allowing NULL in position. Is there a way to temporarily allow NULL similar to how SET FOREIGN_KEY_CHECKS=0; can disable foreign keys?
First delete all the records and then reinsert them. This might result in performance issues as there are indexes on the table which will need to be recreated.
All I can think is that you need to first change all the positions to some other values that aren't in the range of new position values you ultimately need to set, but are still unique within the rows.
An easy way to do this, assuming your position column is a signed integer, is to set all the positions to their opposite (negative) value. They'll remain unique, but they won't be in the set of the new values.
You can do this in a transaction along with your subsequent updates, so no other concurrent transaction will ever see the negative values.
BEGIN;
UPDATE MyTable SET position = -position;
UPDATE MyTable SET position = 2 WHERE id = 1;
...etc...
COMMIT;
This is a hack. The sign bit of the integer is being used for a purpose other than showing negative numbers.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
i have a task to complete. there is a many to many relationship. the bridge table has been made which looks like
left id right id
+----------+---------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
| 2 | 8 |
| 3 | 1 |
| 3 | 2 |
| 3 | 4 |
| 4 | 1 |
| 4 | 2 |
| 4 | 3 |
| 4 | 5 |
| 5 | 1 |
| 5 | 2 |
| 5 | 4 |
| 5 | 6 |
| 5 | 7 |
+----------+---------+
i have to display the left id = right id in one row
for example
for left id 1
left1 | right1 righ 2
for left id 3
left3 | right1 right2 right 4
how do i do this ? i have tried joining table , doesn't work
I think you can use a simple query to acheive this using GROUP BY and GROUP_CONCAT()
SELECT left_id, GROUP_CONCAT(right_id SEPARATOR ' ') as rigth_id
FROM left-right
GROUP BY left_id;
This is a reasonably straightforward application of GROUP_CONCAT() and GROUP BY. (http://sqlfiddle.com/#!9/ed7e1/2/0)
SELECT leftId,
GROUP_CONCAT(rightId ORDER BY rightId) rightIds
FROM bridge
GROUP BY leftId
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Table1 - Payout Requests
`
|--------|-----------|-----------|
| id | Receiver | Balance |
|--------|-----------|-----------|
| 1 | user1 | 2000 |
|--------|-----------|-----------|
| 2 | user2 | 1500 |
|--------|-----------|-----------|`
Table2 - Donars
`
|--------|-----------|-----------|
| id | Donar | Amount |
|--------|-----------|-----------|
| 1 | love | 1500 |
|--------|-----------|-----------|
| 2 | don1 | 1000 |
|--------|-----------|-----------|`
Now my question; What piese of code will make Adjustments of both the tables so that data from these two tables goes in 3rd table in the following way
Table3 - Links
`
|--------|-----------|-----------|----------|
| id | Donar | Receiver | Amount |
|--------|-----------|-----------|----------|
| 1 | love | user1 | 1500 |
|--------|-----------|-----------|----------|
| 2 | don1 | user1 | 500 |
|--------|-----------|-----------|----------|
| 3 | don1 | user2 | 500 |
|--------|-----------|-----------|----------|`
AND now Table 1 & Table 2 will be Follows -
Table1 - Payout Requests
`
|--------|-----------|-----------|
| id | Receiver | Balance |
|--------|-----------|-----------|
| 2 | user2 | 1000 |
|--------|-----------|-----------|`
Table2 - Donars
`
|--------|-----------|-----------|
| id | Donar | Amount |
|--------|-----------|-----------|
| Nothing |
|--------|-----------|-----------|`
In the first step you should have a foreign key on Donars table which save id of Payout Requests. for example pr_id
You can use INNER JOIN like this:
SELECT `t2`.`id`, `t2`.`Donar`, `t1`.`Receiver `, `t1`.Balance - `t2`.`Amount` AS `Adjustment` FROM `table1` AS `t1` INNER JOIN `table2` AS `t2` ON `t2`.`pr_id` = `t1`.id
I have 14 tables (one for every year) with product code, firm name and invoice numbers. Main structure of table is identical (product code, ID), but there can be some variables in names of firms.
Table2011
| ID | productcode | firm1 | firm2 | firm3 | etc |
| 1 | G-00001 | 2;5;40| 32;67 | | 150 |
| 2 | G-00005 | | 50 | | |
|etc | | | | | |
Table2010
| ID | productcode | firm1 | firm2 | firm3 |etc |
| 1 | G-00001 | 1;10 | | 55 | |
| 2 | G-00003 | | 2 | | |
| 3 | G-00005 | | 50 | 40 | |
| etc| | | | | |
Table2009
...
Column Firm1 do not usually equals to same firm as firm 1 in other table
I am using table editor to work with tables (adding columns to table, editing values…).
I would like to know if it is possible to achieve result like below. It is above my PHP skills.
Product G-00001 page
…
<UL>
<LI>Year 2011: 150etc; 67firm2; 40firm1; 32firm2; 5firm1; 2firm1</LI>
<LI>Year 2010: 55firm3; 10firm1; 1firm1</LI>
<LI>Year 2009: ...</LI>
...
</UL>
…
Lemme begin with book recommendation : SQL Antipatterns. You will need it, doesn't matter if you caused this mess or ar just assigned to fix it.
If i was in your place, first thing would do would be to fix the database structure. This is madness. You do not need a new table for each year and new column for each company. Database is not a form of Excel spreadsheet.
Invoices Years Companies
----------------- ------------- ---------------
| product_code PK | | year_id PK | | company_id PK |
| company_id FK | | number | | title |
| amount | ------------- ---------------
| year_id FK |
-----------------
Where PK - primary key and FK - foreign key.
This structure would make the gathering of information much much much MUCH easier.
If you just want to display the data and not worry about the restructuring just yet you can use a JOIN to display the information from all the tables.
Although I would agree with teresko you really need to redesign that database. It is not maintainable the way it is.