Is there a way to create an "EQUAL" constraint in Mysql?
Imagine I have a table like this
tb_1:
id | id_fk | order | id_tb_2 | Column D
----------------------------------------
1 | 1 | 1 | 10 | AAA
2 | 1 | 2 | 20 | BBB
3 | 2 | 1 | 30 | CCC
4 | 3 | 1 | 40 | DDD
And:
tb_2:
id_tb_2 | id_type
------------------
10 | 100
20 | 200
30 | 300
40 | 400
And:
tb_3:
id_type | model | other_prop
--------------------------------
100 | model_A | A
200 | model_A | B
300 | model_B | C
400 | model_C | D
I want to make sure that tb_2.id_type.model are going to be equal for same values of id_fk and different order.
So I have a UNIQUE constraint for [id_fk, order]
And I need a EQUAL constraint for [id_fk, id_tb_2.id_type.model]
This way, I shouldn't be able to create a value in tb_1 like:
id | id_fk | order | id_tb_2 | Column D
----------------------------------------
1 | 1 | 1 | 10 | AAA
2 | 1 | 2 | 20 | BBB
5 | 1 | 3 | 30 | EEE <--- This has a different model in tb_2
How can I create one?
A solution using proper relational normalization is to drop the tb_1.Column D column.
Then the reference to tb_2.id_tb_2 and by extension to tb_3.id_type will be unambiguous.
tb_1:
id | id_fk | order | id_tb_2
----------------------------
1 | 1 | 1 | 10
2 | 1 | 2 | 20
3 | 2 | 1 | 30
4 | 3 | 1 | 40
In other words, by including Column D in tb_1, you're violating Third Normal Form, because Column D is an attribute that depends on something other than the primary key of tb_1.
But I'm not sure you've told us the full scope of the problem you're trying to solve.
You can't.
The only constraints that relate data from multiple tables are FOREIGN KEY constraints; and they are very limited about the relationship they check: a list of columns against another list of columns on another/same table.
All other relational constraints (such as UNIQUE or CHECK) have a table scope.
Related
I have 3 tables with corresponding fields.
Table 1 (List of Machines)
Machine_No | Machine_Description
1 | Hitachi
2 | Jet Printer
3 | Sumi
Table 2 (List of Manpower)
ID_Number | Employee_Name | Machine_No
1 | Taylor | 3
2 | James | 2
3 | David | 1
Table 3 (Actual Manpower use per machine)
Machine_No | Employee_Number | Date Posted
1 | 1 | 15-10-2019
1 | 2 | 15-10-2019
1 | 3 | 15-10-2019
Now... I want the results to go like this.
Machine_Now | Count(Employee Number) | Date_Posted
1 | 3 | 15-10-2019
Try this, it may work, if I understand your question correctly.
select Machine_No,Date_Posted,count(*) from Table3 group by Machine_No,Date_Posted;
This question already has an answer here:
MySQL pivot row into dynamic number of columns
(1 answer)
Closed 3 years ago.
Say I have a table like so
+----+----------+------+
| id | name | type |
+----+----------+------+
| 1 | apple | F |
| 1 | pear | F |
| 1 | cucumber | V |
| 2 | orange | F |
| 2 | grass | NULL |
| 2 | broccoli | V |
| 3 | flower | NULL |
| 3 | tomato | NULL |
+----+----------+------+
I want to end up with a table that counts the number of elements for each type (including NULL types) AND for each id, like this:
+----+-----------------+--------------+--------------+
| id | type_NULL_count | type_F_count | type_V_count |
+----+-----------------+--------------+--------------+
| 1 | 0 | 2 | 1 |
| 2 | 1 | 1 | 1 |
| 3 | 2 | 0 | 0 |
+----+-----------------+--------------+--------------+
This is rather easy to do, but is there a way (a query I can write or something else) such that when I go back and edit one of the type fields in the first table, I end up with a properly updated count table?
For example, let's say I want to add a new type (type X) and change the type field for flower from NULL to X. Is there a way to end up with the following table without having to rewrite the query or add more statements?
+----+-----------------+--------------+--------------+--------------+
| id | type_NULL_count | type_F_count | type_V_count | type_X_count |
+----+-----------------+--------------+--------------+--------------+
| 1 | 0 | 2 | 1 | 0 |
| 2 | 1 | 1 | 1 | 0 |
| 3 | 1 | 0 | 0 | 1 |
+----+-----------------+--------------+--------------+--------------+
I'm not sure if this is the best way to do this, so I am open to suggestions
Having a secondary table which it's number of columns changes based on your first table is not a viable option.
Do you need to keep the result in a table or it will be displayed as a report?
I think a better way to do this is using the SQL below calculate counts by id plus type and display using your data display tool the way you like it.
select id, type, count(*) count
from d
group by 1,2
order by 1,2
The output would be
id type count
1 F 2
1 V 1
2 F 1
2 V 1
2 1
3 X 1
3 1
I have two tables:
Table a:
+----+------+
| id | data |
+----+------+
| 1 | 450 |
| 2 | 500 |
| 3 | 550 |
| 4 | 600 |
| 5 | 650 |
+----+------+
Table b:
+----+------+------+
| id | a_id | note |
+----+------+------+
| 1 | 2 | 25 |
| 2 | 5 | 10 |
+----+------+------+
I need a query that returns a table that consists of every row from table a with the notes from table b. I want 0 filled in where a note isn't available on a row. I want it to look like this:
+----+------+------+
| id | data | note |
+----+------+------+
| 1 | 450 | 0 |
| 2 | 500 | 25 |
| 3 | 550 | 0 |
| 4 | 600 | 0 |
| 5 | 650 | 10 |
+----+------+------+
How do I do that?
select a.id, a.data, coalesce(b.note, 0) as note
from a
left join b on a.id = b.a_id
What are you looking for is called LEFT/RIGHT JOIN. This question will give you more details about what they are.
Assume you have a query like:
SELECT * FROM a LEFT JOIN b ON some_condition;
Then, its output will contain every row from table a, along with data from table b where the condition is met. For rows where the condition is not met, the columns with data from b will contain null.
I have 3 tables like the tables below
tbl_GasExpense
GID | Gas_Expense | Date_Occured
-----------------------------------
1 | 400 | 11/30/2014
2 | 500 | 11/30/2014
3 | 300 | 11/30/2014
tbl_Food Expense
FID | Food_Expense | Date_Occured
-----------------------------------
1 | 450 | 11/30/2014
2 | 250 | 11/30/2014
3 | 390 | 11/30/2014
tbl_Drink Expense
DID | Drink_Expense | Date_Occured
-----------------------------------
1 | 150 | 11/30/2014
2 | 250 | 11/30/2014
3 | 360 | 11/30/2014
and with those tables above, I want an output like this.
ID | Gas_Sum | Food_Sum | Drink_Sum | Date_Occured
-----------------------------------------------------------
1 | 1200 | 1090 | 760 | 11/30/2014
The values of the three tables from which are dated 11/30/2014 are summed in table four.
Using the IDs from the first three tables as foreign keys in the table 4 to establish a relation. Gas_Sum is a mask for GID, Food_Sum for FID, Drink_Sum for DID.
Thanks guys, but I already have my answer now after several trial and errors
.. it is something like this. but this is on my own code
SELECT o.eh_ID, SUM(o.others_amt) as 'OTHERS SUM'
FROM tbl_Others o
INNER JOIN tbl_ExpenseHead hd ON hd.eh_ID = o.eh_ID
GROUP BY o.eh_ID
I guess, the name of the question is strange, but I don't know how to state it correctly, so I'll try to describe the problem. Say, we have two tables:
1)
id | unit_name | strength | health
1 | private | 10 | 10
2 | general | 5 | 5
n | someone | 123 | 321
2)
id | rules | who_has_this_rule
1 | rule1 | 1
2 | rule2 | 2
3 | rule3 | 1
4 | rule4 | 1
The field "who_has_this_rule" correspondes with id of the first table.
But I can't figure out what to do if a unit should have more than one rule in his profile. For example, private should have rule1 and rule4. How to do this?
What you need is a join table.
A third table to join rule and units
unit_rules
id | unit_id | rule_id
1 | 1 | 1
2 | 1 | 4
3 | 2 | 1
You can have a primary key(id) or compound key(unit_id and rule_id)