Not duplicate values ON DUPLICATE KEY UPDATE - php

I'm entering data in the database, but when the value of the slug and the site is duplicated it must update. But I can not succeed every time it adds a new line with the repeated data.
mysql;
+------------+--------------+------+-----+-----------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+-----------+-------+
| id_tag | int(11) | NO | PRI | None | |
| nome_tag | varchar(200) | NO | | None | |
| slug_tag | varchar(200) | NO | | None | |
| usuario_tag| int(3) | NO | | None | |
+------------+--------------+------+-----+-----------+-------+
DATA;
+------------+--------------+---------+------------+
| id_tag | nome_tag | slug_tag| usuario_tag|
+------------+--------------+---------+------------+
| 1 | Maria | maria | 1 |
| 2 | Car | car | 1 |
| 3 | Musa | musa | 1 |
| 4 | Tota | tota | 1 |
| 5 | Maria | maria | 1 |
+------------+--------------+------+-----+---------+
$vai = $conn->prepare("INSERT INTO tab_tags (nome_tag, slug_tag, usuario_tag) VALUES('$nome_tag', '$slug_tag', $usuario_tag) ON DUPLICATE KEY UPDATE slug_tag = '$slug_tag'");
$vai->execute();
var_dump($vai->queryString);
string 'INSERT INTO tags (nome_tag, slug_tag, usuario_tag) VALUES('Maria', 'maria', 1) ON DUPLICATE KEY UPDATE slug_tag = 'maria'' (length=148)
How do I duplicate it does not, I would like to do an Update, but he always doubles the data.

You need an UNIQUE index on columns nome_tag and slug_tag:
ALTER TABLE tab_tags ADD UNIQUE INDEX `nome_slug` (`nome_tag`, `slug_tag`)

Related

How do I merge all product tables while adding new column?

Summary
I have many tables that hold product information. The tables are all named like this:
p_productCategory
Here is some real data (showing only three for space)
+---------------------+
| Tables_in_global |
+---------------------+
| orders |
| p_audio_buzzers |
| p_audioaccessories |
| p_batteries_primary |
+---------------------+
The Task At Hand
I need to consolidate all these tables into ONE table. They all have the same column names:
+--------------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------------+--------------+------+-----+---------+-------+
| Datasheets | varchar(128) | YES | | NULL | |
| Image | varchar(85) | YES | | NULL | |
| DigiKey_Part_Number | varchar(46) | YES | | NULL | |
| Manufacturer_Part_Number | varchar(47) | YES | | NULL | |
| Manufacturer | varchar(49) | YES | | NULL | |
| Description | varchar(34) | YES | | NULL | |
| Quantity_Available | int(11) | YES | | NULL | |
| Factory_Stock | bit(1) | YES | | NULL | |
| Unit_Price | decimal(9,5) | YES | | NULL | |
| qty | bit(1) | YES | | NULL | |
| Minimum_Quantity | int(11) | YES | | NULL | |
| Packaging | varchar(4) | YES | | NULL | |
+--------------------------+--------------+------+-----+---------+-------+
Also, I need to add a new column "category", which would be the table name, ie: audioaccessories, batteries_primary
Question:
How would I go about making a new "products" table, and inserting all the records from all the tables prefaced with a p_ ?
Thank you for looking. I am stuck. I looked at some other "merge table" questions on here, but none were similar enough for me to use.
Write a query by using UNION between all the tables. Make sure to statically add "category" for each projection. Attach the query block right after CREATE TABLE segment.
Example:CREATE TABLE new_table_name AS SELECT *,'audio_buzzers' AS category FROM p_audio_buzzers UNION SELECT *,'audioaccessories' AS category FROM p_audioaccessories UNION SELECT *,'batteries_primary' AS category FROM p_batteries_primary

how to fetch data from multiple tables

So I normalize my database and it seems quite complicated for me to fetch or update records in tables.
I have 5 tables ( details, country, materials, vendor_countries, vendor_materials). Actually "details" is my main table.
country table have two column (id, name).
materials table also have two column(id, name).
details table have personnel information about vendors (name, email, phone, address).
A vendor could have multiple countries and materials so I made two more tables vendor_countries and vendor_materials and their column are (did,cid), (did,mid).
"did" is the id of each vendor coming from details table and cid,mid is the country id and material id coming from country and material table.
Now I want to fetch vendors along with their countries and materials.
here is my details table, vendor_countries and vendor_materials tables
so far I made a query which is shown below:
select dt.vendor,
dt.email,
dt.address,
c.country,
m.material,
c.country
from country c
inner join vendor_countries vc on (c.id = vc.cid)
right join details dt on (dt.id = vc.did)
left join vendor_materials vm on dt.id = vm.did
left join material m on vm.mid = m.id
and i am getting results like this:
which is not right it should be in 3 rows because "ali" vendor works in 3 countries and 3 materials. I am looking for some smart solution which also not slow down my page. Thanks in advance.
In the absence of any response regarding table schema I tried to re-create the tables based upon the descriptions above -prefixing each table with v_ so I could group the tables in this db and referencing did as vid ( vendor id ) and populating with what I believed to be the sample data from the question
mysql> describe v_country;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(50) | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
mysql> describe v_details;
+---------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| vendor | varchar(50) | YES | | NULL | |
| email | varchar(50) | YES | | NULL | |
| phone | varchar(50) | YES | | NULL | |
| address | varchar(50) | YES | | NULL | |
+---------+------------------+------+-----+---------+----------------+
mysql> describe v_materials;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(50) | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
mysql> describe v_vendor_materials;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| vid | int(10) unsigned | NO | MUL | 0 | |
| mid | int(10) unsigned | NO | MUL | 0 | |
+-------+------------------+------+-----+---------+----------------+
mysql> describe v_vendor_countries;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| vid | int(10) unsigned | NO | MUL | 0 | |
| mid | int(10) unsigned | NO | MUL | 0 | |
+-------+------------------+------+-----+---------+----------------+
mysql> select * from v_country;
+----+----------+
| id | name |
+----+----------+
| 1 | pakistan |
| 2 | India |
| 3 | Iran |
+----+----------+
mysql> select * from v_details;
+----+--------+------------------+---------------+-----------+
| id | vendor | email | phone | address |
+----+--------+------------------+---------------+-----------+
| 1 | harris | harris#gmail.com | 0141 236 4523 | nowhere |
| 2 | Boris | boris#gmail.com | 0141 451 7845 | somewhere |
| 3 | Doris | doris#gmail.com | 0141 353 7845 | anywhere |
+----+--------+------------------+---------------+-----------+
mysql> select * from v_materials;
+----+---------+
| id | name |
+----+---------+
| 1 | ceramic |
| 2 | iron |
| 3 | plastic |
+----+---------+
mysql> select * from v_vendor_materials;
+----+-----+-----+
| id | vid | mid |
+----+-----+-----+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
+----+-----+-----+
mysql> select * from v_vendor_countries;
+----+-----+-----+
| id | vid | mid |
+----+-----+-----+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
+----+-----+-----+
mysql> select * from v_details d
left outer join v_vendor_materials vm on vm.vid=d.id
left outer join v_vendor_countries vc on vc.vid=d.id
left outer join v_materials m on m.id=vm.id
left outer join v_country c on c.id=vc.id;
+----+--------+------------------+---------------+-----------+------+------+------+------+------+------+------+---------+------+----------+
| id | vendor | email | phone | address | id | vid | mid | id | vid | mid | id | name | id | name |
+----+--------+------------------+---------------+-----------+------+------+------+------+------+------+------+---------+------+----------+
| 1 | harris | harris#gmail.com | 0141 236 4523 | nowhere | 1 | 1 | 1 | 1 | 1 | 1 | 1 | ceramic | 1 | pakistan |
| 2 | Boris | boris#gmail.com | 0141 451 7845 | somewhere | 2 | 2 | 2 | 2 | 2 | 2 | 2 | iron | 2 | India |
| 3 | Doris | doris#gmail.com | 0141 353 7845 | anywhere | 3 | 3 | 3 | 3 | 3 | 3 | 3 | plastic | 3 | Iran |
+----+--------+------------------+---------------+-----------+------+------+------+------+------+------+------+---------+------+----------+
or, a more selective query
select
d.`id` as `vid`,
d.`vendor`,
d.`email`,
d.`phone`,
d.`address`,
m.`name` as `material`,
c.`name` as `country`
from v_details d
left outer join v_vendor_materials vm on vm.vid=d.id
left outer join v_vendor_countries vc on vc.vid=d.id
left outer join v_materials m on m.id=vm.id
left outer join v_country c on c.id=vc.id;
+-----+--------+------------------+---------------+-----------+----------+----------+
| vid | vendor | email | phone | address | material | country |
+-----+--------+------------------+---------------+-----------+----------+----------+
| 1 | harris | harris#gmail.com | 0141 236 4523 | nowhere | ceramic | pakistan |
| 2 | Boris | boris#gmail.com | 0141 451 7845 | somewhere | iron | India |
| 3 | Doris | doris#gmail.com | 0141 353 7845 | anywhere | plastic | Iran |
+-----+--------+------------------+---------------+-----------+----------+----------+

SQL Union 1 Column within Larger Query with Laravel ORM?

I'm currently storing addresses for multiple different objects. So there is addresses for jobs, companies, etc.
I want to be able to get all addresses.* and a union of jobs.job_title & companies.company_name to select an object_name for each addresses record.
Address.php (Model)
static $object_type = [
1 => 'Company',
2 => 'Job',
];
static public function getObjectTypes() {
return self::$object_type;
}
static public function getObjectTypeName($key) {
return self::$object_type[$key];
}
static public function getAddresses(){
$addresses = Address::select(
'addresses.*'
)->where('addresses.soft_deleted', 0);
$addresses->limit(20);
return $addresses->get();
}
The current schema for addresses table:
+-------------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------------------+------+-----+---------+----------------+
| id | int(12) unsigned | NO | PRI | NULL | auto_increment |
| object_id | int(12) | YES | MUL | 0 | |
| object_type | tinyint(3) | YES | | 1 | |
| address | varchar(255) | YES | | NULL | |
| soft_deleted | tinyint(3) unsigned | YES | | 0 | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL | |
+-------------------+---------------------+------+-----+---------+----------------+
The current schema for jobs table:
+-----------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+----------------+
| id | int(12) unsigned | NO | PRI | NULL | auto_increment |
| company_id | int(12) | YES | | 0 | |
| job_title | varchar(99) | YES | | NULL | |
| soft_deleted | tinyint(3) unsigned | YES | | 0 | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL |
+-----------------+---------------------+------+-----+---------+----------------+
The current schema for companies table:
+-----------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+----------------+
| id | int(12) unsigned | NO | PRI | NULL | auto_increment |
| company_name | varchar(99) | YES | | NULL | |
| soft_deleted | tinyint(3) unsigned | YES | | 0 | |
| created_at | datetime | NO | | NULL | |
| updated_at | datetime | NO | | NULL |
+-----------------+---------------------+------+-----+---------+----------------+
My question is: How would I create the union and return the data needed based on the above structure?
Here is a SQLFiddle of what I think you are after. This is a very simplified schema to illustrate what is being done:
addresses
id | objectId | objectType | address
1 | 1 | 1 | 4657
2 | 1 | 3 | 3465
3 | 2 | 4 | 4536
4 | 1 | 2 | 3098
5 | 2 | 1 | 5647
6 | 2 | 2 | 8989
7 | 1 | 4 | 4563
8 | 2 | 3 | 2345
companies
id | name
1 | 'Acme Anvils'
2 | 'McBarfles'
3 | 'Noke'
4 | 'Stab Mart'
jobs
id | companyId | title
1 | 4 | 'Fly Swatter'
2 | 3 | 'Palm Greaser'
3 | 2 | 'McBarfle Burger Tender'
4 | 1 | 'Shill'
Assuming that objectType 1 = Company and objectType 2 = Job:
SELECT
'Company' AS objectType,
c.name,
a.address
FROM addresses a
INNER JOIN companies c
ON a.objectId = c.id
WHERE a.objectType = 1
UNION ALL
SELECT
'Job' AS objectType,
j.title,
a.address
FROM addresses a
INNER JOIN jobs j
ON a.objectId = j.id
WHERE a.objectType = 2
This breaks the joins up into sections based on the objectType in the addresses table, then UNION ALLs the results together to get the final list of addresses and object names:
objectType | name | address
Company | Acme Anvils | 4657
Company | Noke | 3465
Company | McBarfles | 3098
Company | Stab Mart | 4563
Job | Shill | 4536
Job | Fly Swatter | 5647
Job | Palm Greaser | 8989
Job | McBarfle Burger Tender | 2345
Note that you would have to manually add additional queries to be UNION ALLed for each possible value of objectType.

tag cloud with mysql

Is there any other way to make tag cloud from mysql without temporary tables?
mysql> explain wallpaper_keywords;
+--------------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------------------+------+-----+---------+----------------+
| id | mediumint(7) unsigned | NO | PRI | NULL | auto_increment |
| wallpaper_id | mediumint(7) unsigned | YES | MUL | NULL | |
| keyword_id | smallint(5) unsigned | YES | MUL | NULL | |
+--------------+-----------------------+------+-----+---------+----------------+
mysql> explain keywords;
+---------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-----------------------+------+-----+---------+----------------+
| id | mediumint(7) unsigned | NO | PRI | NULL | auto_increment |
| keyword | varchar(32) | YES | UNI | NULL | |
+---------+-----------------------+------+-----+---------+----------------+
SELECT k.keyword,count(k.keyword) AS count FROM keywords k Left Join wallpaper_keywords wk ON wk.keyword_id = k.id GROUP BY wk.keyword_id, k.keyword ORDER BY count DESC limit 100;
+----------+-------+
| keyword | count |
+----------+-------+
| computer | 10 |
| road | 4 |
| tree | 4 |
| window | 4 |
| nature | 4 |
| forest | 3 |
| cars | 3 |
| mazda | 3 |
| abstract | 3 |
| funny | 3 |
| sport | 3 |
| sea | 3 |
| city | 3 |
| warrior | 2 |
| bird | 2 |
| lights | 1 |
| summer | 1 |
| space | 1 |
| dusk | 1 |
| ubuntu | 1 |
+----------+-------+
explain:
+----+-------------+--------------------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| 1 | PRIMARY | keywords | index | NULL | keyword | 99 | NULL | 20 | Using index; Using temporary; Using filesort |
| 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 54 | |
| 2 | DERIVED | wallpaper_keywords | index | NULL | PRIMARY | 3 | NULL | 54 | |
+----+-------------+--------------------+-------+---------------+---------+---------+------+------+----------------------------------------------+
3 rows in set (0.00 sec)
EDIT
another query:
SELECT count,k.keyword from (SELECT * , count(wk.keyword_id) AS count FROM wallpaper_keywords wk GROUP BY wk.keyword_id LIMIT 50000) as data left join keywords as k on k.id = data.keyword_id order by count desc limit 500
+----+-------------+------------+--------+---------------+------------+---------+-----------------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+------------+---------+-----------------+------+----------------+
| 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 20 | Using filesort |
| 1 | PRIMARY | k | eq_ref | PRIMARY | PRIMARY | 3 | data.keyword_id | 1 | |
| 2 | DERIVED | wk | index | NULL | keyword_id | 3 | NULL | 59 | |
+----+-------------+------------+--------+---------------+------------+---------+-----------------+------+----------------+
the question would be now - is there any better solution? cheaper (SHOW STATUS LIKE 'last_query_cost';) way to count it?
For counting total value for every keyword you cau use additional field (total_count) in table keywords and by every adding new keyword add +1 to this field - it's really simpler for your database in future, when you will have 100 000 records.

mysql query takes 145 seconds

I have a a mysql db with myisam engine. Along with many other table I have this table "et" which has around 8137037 records.
I have created indexes (individual index of column hname and pnum, it did not help much later created joint index of hname and pnum and it help execute within a second)such that queries as follows
select st from et where hname='name' and pnum='1' limit 1
execute fast (with in a second) but the problem is I must execute this query
select st from et where hname='name' and pnum='1' order by id limit 1
where id is the primary key of the table and this query sometimes take 145 seconds :(
how can i resolve this issue?
table structure
mysql> describe et;
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| client_id | int(11) | YES | MUL | NULL | |
| down_id | bigint(20) | YES | MUL | NULL | |
| port_index | int(11) | YES | | NULL | |
| date1 | bigint(20) | YES | MUL | NULL | |
| username | varchar(50) | YES | | NULL | |
| hname | varchar(80) | YES | MUL | NULL | |
| pnum | varchar(10) | YES | MUL | NULL | |
| status | int(3) | YES | MUL | NULL | |
| department | int(2) | YES | MUL | NULL | |
| comments | text | YES | | NULL | |
| issue | int(1) | YES | MUL | NULL | |
+------------+-------------+------+-----+---------+----------------+
12 rows in set (0.06 sec)
Indexes
mysql> show indexes from et;
+-----+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
|Table| Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| et | 0 | PRIMARY | 1 | id | A | 8137037 | NULL | NULL | | BTREE | |
| et | 1 | status | 1 | status | A | 12 | NULL | NULL | YES | BTREE | |
| et | 1 | down_id | 1 | down_id | A | 4068518 | NULL | NULL | YES | BTREE | |
| et | 1 | issue_idx | 1 | issue | A | 8137037 | NULL | NULL | YES | BTREE | |
| et | 1 | hname_idx | 1 | hname | A | 283 | NULL | NULL | YES | BTREE | |
| et | 1 | pname_idx | 1 | pnum | A | 136 | NULL | NULL | YES | BTREE | |
| et | 1 | clientid_idx | 1 | client_id | A | 8137037 | NULL | NULL | YES | BTREE | |
| et | 1 | date1_idx | 1 | date1 | A | 8137037 | NULL | NULL | YES | BTREE | |
| et | 1 | department_idx | 1 | department | A | 2712345 | NULL | NULL | YES | BTREE | |
| et | 1 | hp_idx | 1 | hname | A | 283 | NULL | NULL | YES | BTREE | |
| et | 1 | hp_idx | 2 | pnum | A | 4834 | NULL | NULL | YES | BTREE | |
+-----+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
11 rows in set (0.06 sec)
Explain Plan
mysql> explain select status from et where hname='mmah' and port_num='1' limit 1;
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-------------+
| 1 | SIMPLE | error_trap | ref | hname_idx,pname_idx,hostport_idx | hostport_idx | 96 | const,const | 37 | Using where |
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-------------+
1 row in set (0.02 sec)
mysql> explain select status from et where host_name='mmah' and pnum='1' order by id desc limit 1;
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-----------------------------+
| 1 | SIMPLE | error_trap | ref | hname_idx,pname_idx,hostport_idx | hostport_idx | 96 | const,const | 37 | Using where; Using filesort |
+----+-------------+------------+------+----------------------------------+--------------+---------+-------------+------+-----------------------------+
1 row in set (0.00 sec)
Have you tried creating an index of (id, hname,pnum)?
If your index includes and is already ordered by ID then that effectively removes that concern.
There is no reason you cannot include ID in another index, just because it is also the primary.
Create an index in the table that contains hname and pnum.
This will cause MYSQL to create a shadow table, which only contains those 2 parameters, and whenever those 2 parmaters are used in a where, it looks in that shadow table, and finds them very fast.

Categories