Select duplicate urls? - mysql

I want to turn off .html from the category paths. When I toggle the setting off in the admin panel I get a unique constraint error. We have hundreds of categories, pages and products so finding which one or more urls are conflicting is not feasible via the admin panel. As such, I'm looking in the url_rewrite table.
+------------------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+----------------------+------+-----+---------+----------------+
| url_rewrite_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| entity_type | varchar(32) | NO | | NULL | |
| entity_id | int(10) unsigned | NO | MUL | NULL | |
| request_path | varchar(255) | YES | MUL | NULL | |
| target_path | varchar(255) | YES | MUL | NULL | |
| redirect_type | smallint(5) unsigned | NO | | 0 | |
| store_id | smallint(5) unsigned | NO | MUL | NULL | |
| description | varchar(255) | YES | | NULL | |
| is_autogenerated | smallint(5) unsigned | NO | | 0 | |
| metadata | varchar(255) | YES | | NULL | |
+------------------+----------------------+------+-----+---------+----------------+
I'm starting with a generic "find all duplicate rows" query and trying to build out to select request_paths if they contain .html or not, however I'm struggling with the query. Here's the generic sql:
select count(request_path), request_path, store_id from url_rewrite group by request_path, store_id having count(request_path) > 1;
I've tried variations of count(replace(request_path, '.html','')) but I'm not getting any results out (e.g. select count(replace(request_path, '.html','')), request_path, store_id from url_rewrite group by request_path, store_id having count(replace(request_path, '.html','')) > 1;).
If I had the urls:
my_slug.html
my_slug
what sql query do I need to select to get my_slug (and hopefully other row data?) from the table?

Related

Join between two tables based on multiple criteria

I have a table accounts with columns ip_from, ip_to, start_time, end_time, bytes.
There is a second table called all_audit with columns project, ip, time.
I need to join the tables in order to get a resulting table with columns for project, time and bytes.
Things that need to be considered are that time only matches with records which fall between start_time and end_time. ip can match either ip_from or ip_to.
The schema for the two tables are:
accounts
+----------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------------------+------+-----+---------+-------+
| ip_from | char(15) | NO | PRI | NULL | |
| ip_to | char(15) | NO | PRI | NULL | |
| bytes | bigint(20) unsigned | NO | | NULL | |
| start_time | datetime | NO | PRI | NULL | |
| end_time | datetime | YES | | NULL | |
+----------------+---------------------+------+-----+---------+-------+
all_audit
+-----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| project | varchar(255) | YES | | NULL | |
| ip | varchar(32) | YES | MUL | NULL | |
| time | timestamp | YES | | NULL | |
+-----------+------------------+------+-----+---------+----------------+
result
+-----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+----------------+
| project | varchar(255) | YES | | NULL | |
| time | timestamp | YES | | NULL | |
| bytes | bigint(20) unsigned| NO | | NULL | |
+-----------+------------------+------+-----+---------+----------------+
I know it will be a join but I just don’t know where to start. Pointers will be very helpful as I am not that competent yet in sql statements but willing to learn.
I suspect you are looking for something like this:
SELECT aa.project
, aa.time
, a.bytes
FROM all_audit aa
JOIN accounts a
on (aa.ip = a.ip_from OR aa.ip = a.ip_to)
AND aa.time BETWEEN a.start_time AND a.end_time

Update MySQL table based on results for joining to tables

I have three tables, emails, person_details and data_providers. Basically all of my users id, email, and current assigned data_providers_id are stored in the emails table.
The second table, person_details contains demographic information collected by multiple data providers, each row identified by an emails_id that is relational to the emails.id data_providers_id that is relational to the third table data_providers.id
The third table, data_providers contains each of my data providers id, name, and precedence.
Basically, a users information could be collected from multiple sources, and I need to UPDATE emails set data_providers_id = based on a select that would JOIN the person_details table and the data_providers table sorting by data_providers.precedence DESC then person_details.import_date ASC and use the first value (highest precedence, then oldest import_date).
I was trying to build the query, but my subquery is returning more than one row. This query is a little over my head, hoping someone more experienced with complex queries might be able to point me in the right direction.
UPDATE emails
SET emails.data_providers_id =
SELECT person_details.data_providers_id
FROM person_details
LEFT JOIN data_providers ON person_details.data_providers_id = data_providers.id
ORDER BY data_providers.percent_payout ASC, person_details.import_date ASC ;
Here are some details about the three tables if this helps. Any guidance would be MUCH appreciated. Thanks in advance :)
emails table:
+-------------------+---------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------------------+------+-----+---------------------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| data_providers_id | tinyint(3) unsigned | NO | MUL | NULL | |
| email | varchar(255) | NO | UNI | NULL | |
+-------------------+---------------------+------+-----+---------------------+----------------+
person_details:
+-------------------+---------------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------------------+------+-----+---------------------+-------+
| emails_id | int(11) unsigned | NO | PRI | NULL | |
| data_providers_id | tinyint(3) unsigned | NO | PRI | NULL | |
| fname | varchar(255) | YES | | NULL | |
| lname | varchar(255) | YES | | NULL | |
| address_line1 | text | YES | | NULL | |
| address_line2 | text | YES | | NULL | |
| city | varchar(255) | YES | | NULL | |
| state | varchar(2) | YES | | NULL | |
| zip5 | varchar(5) | YES | | NULL | |
| zip4 | varchar(4) | YES | | NULL | |
| home_phone | varchar(10) | YES | | NULL | |
| mobile_phone | varchar(10) | YES | | NULL | |
| work_phone | varchar(10) | YES | | NULL | |
| dob | date | YES | | NULL | |
| gender | varchar(1) | YES | | NULL | |
| ip_address | varchar(15) | NO | | NULL | |
| source | varchar(255) | NO | | NULL | |
| optin_datetime | datetime | NO | MUL | NULL | |
| import_date | timestamp | NO | | 0000-00-00 00:00:00 | |
+-------------------+---------------------+------+-----+---------------------+-------+
data_providers table:
+-----------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+---------------------+------+-----+---------+----------------+
| id | tinyint(3) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| precedence | int(2) | YES | | 0 | |
+-----------------+---------------------+------+-----+---------+----------------+
To use a SELECT as an expression you have to put it in parentheses. And to get the first value, use LIMIT 1:
UPDATE emails
SET emails.data_providers_id = (
SELECT person_details.data_providers_id
FROM person_details
LEFT JOIN data_providers ON person_details.data_providers_id = data_providers.id
WHERE person_details.emails_id = emails.id
ORDER BY data_providers.percent_payout ASC, person_details.import_date ASC
LIMIT 1) ;

How to create primary key using multiple columns & Auto increment id?

This is my tables structures
mysql> DESCRIBE sections;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| sec_id | int(5) | NO | PRI | NULL | auto_increment |
| sec_name | varchar(45) | YES | | NULL | |
| sec_type | tinyint(4) | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
mysql> DESCRIBE subjects;
+-----------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+----------------+
| sub_id | int(5) | NO | PRI | NULL | auto_increment |
| sub_name | varchar(45) | YES | | NULL | |
| sections_sec_id | int(5) | NO | MUL | NULL | |
+-----------------+-------------+------+-----+---------+----------------+
mysql> DESCRIBE chapters;
+-----------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+----------------+
| chp_id | int(5) | NO | PRI | NULL | auto_increment |
| chp_name | varchar(45) | YES | | NULL | |
| subjects_sub_id | int(5) | NO | MUL | NULL | |
| sections_sec_id | int(5) | NO | MUL | NULL | |
+-----------------+-------------+------+-----+---------+----------------+
mysql> DESCRIBE questions;
+-----------------+-----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-----------+------+-----+---------+----------------+
| que_id | int(11) | NO | PRI | NULL | auto_increment |
| que_text | text | YES | | NULL | |
| que_created | timestamp | YES | | NULL | |
| chapters_chp_id | int(5) | NO | MUL | NULL | |
| subjects_sub_id | int(5) | NO | MUL | NULL | |
| sections_sec_id | int(5) | NO | MUL | NULL | |
+-----------------+-----------+------+-----+---------+----------------+
mysql> DESCRIBE answers;
+------------------+-----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+-----------+------+-----+---------+----------------+
| ans_id | int(11) | NO | PRI | NULL | auto_increment |
| ans_text | text | YES | | NULL | |
| ans_created | timestamp | YES | | NULL | |
| questions_que_id | int(11) | NO | MUL | NULL | |
| chapters_chp_id | int(5) | NO | MUL | NULL | |
| subjects_sub_id | int(5) | NO | MUL | NULL | |
| sections_sec_id | int(5) | NO | MUL | NULL | |
+------------------+-----------+------+-----+---------+----------------+
Let's assume 'Answers' table
I created the 'ans_id' as the primary key of 'Answers' table, created a another UNIQUE key using (ans_id,questions_que_id,chapters_chp_id,subjects_sub_id,sections_sec_id)
What i want do.
create primary key for 'Answers' table using (ans_id,questions_que_id,chapters_chp_id,subjects_sub_id,sections_sec_id) columns and create Trigger before INSERT to create 'auto_increment' id.
Finally i want to accomplish this
Definition: Primary key is minimal set of attributes needed to determine every row in a table.
UNIQUE index should be {questions_que_id} + {chapters_chp_id} + {subjects_sub_id} +{sections_sec_id} and make sure it is combined as one index with these 4 columns, if you set it as different 4 indexes than you will probably achieve undesired outcome, as Zohar already pointed. From my experience, it could be unpractical to use composite keys like this. For basic table operations (CRUD) you will have to provide a lot of parameters.
Maybe to try this way: autoincremental numeric id as a primary key, the rest of important attributes as UNIQUE index. Then you could count already inserted answers to make sure right number will be assigned to ans_id. Hint: it's maybe easier to achive this from your application layer, not as a trigger or procedure for MySQL. If your users will provide answers as step-by-step, then just save a timestamp and you will know which answer is older so you don't need ans_id at all.

Writing MySQL query with several table joins or multiple select

I am trying to write a MySQL query that gives me results of Organisation Name, its Post Code, any Events that belong to the Organisation and the Post Code of that Event. I've tried all sorts of of join, join and select combinations to no avail. Is this something that is possible ? (I could have a separate table for Org Address and Event Address but it seems like it should be possible to use just one table)
My table structures:
mysql> DESCRIBE cc_organisations;
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| user_id | int(10) unsigned | NO | MUL | NULL | |
| type | enum('C','O') | YES | | NULL | |
| name | varchar(150) | NO | MUL | NULL | |
| description | text | YES | | NULL | |
+-------------+------------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql> DESCRIBE cc_events;
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| org_id | int(10) unsigned | NO | MUL | NULL | |
| name | varchar(150) | NO | MUL | NULL | |
| start_date | int(11) | NO | MUL | NULL | |
| end_date | int(11) | YES | MUL | NULL | |
| start_time | int(11) | NO | | NULL | |
| end_time | int(11) | NO | | NULL | |
| description | text | YES | | NULL | |
+-------------+------------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)
mysql> DESCRIBE cc_addresses;
+--------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| org_id | int(10) unsigned | YES | MUL | NULL | |
| event_id | int(10) unsigned | YES | MUL | NULL | |
| post_code | varchar(7) | NO | MUL | NULL | |
| address_1 | varchar(100) | NO | | NULL | |
| address_2 | varchar(100) | YES | | NULL | |
| town | varchar(50) | NO | | NULL | |
| county | varchar(50) | NO | | NULL | |
| email | varchar(150) | NO | | NULL | |
| phone | int(11) | YES | | NULL | |
| mobile | int(11) | YES | | NULL | |
| website_uri | varchar(150) | YES | | NULL | |
| facebook_uri | varchar(250) | YES | | NULL | |
| twitter_uri | varchar(250) | YES | | NULL | |
+--------------+------------------+------+-----+---------+----------------+
14 rows in set (0.00 sec)
select o.Name, oAddress.PostCode, e.Name, eAddress.PostCode
from cc_organisations o
inner join cc_addresses oAddress on oAddress.org_id = o.id
left outer join cc_events e on e.org_id=o.id
inner join cc_addresses eAddress on eAddress.event_id = e.id
SELECT cco.name as OrgName, cca.post_code as OrgPostCode, cce.id,
cce.org_id, cce.name, cce.start_date, cce.end_date, cce.start_time,
cce.end_time, cce.description
FROM cc_events cce, cc_addresses cca, cc_organisations cco
WHERE cca.event_id = cce.id AND cco.id=cce.org_id
ORDER BY cce.start_date
LIMIT 50;
You can change your sort and limit, I just added those in because I don't know how big your DB is... You may even be able to get away with:
SELECT cco.name as OrgName, cca.post_code as OrgPostCode, cce.*
FROM cc_events cce, cc_addresses cca, cc_organisations cco
WHERE cca.event_id = cce.id AND cco.id=cce.org_id
ORDER BY cce.start_date LIMIT 50;
But im not 100% sure if the 2nd query will bum out or not.
Your address table has the post codes in it; but it also has an organization id and event id foreign keys. We only need to check the event_id from the address table because any event will belong to an organization.
Address's Event matched Event ID
Event's Organization matched Organization ID

mysql problem: populate table from another table but referencing ID instead of name

I'm now trying to populate my 'testMatch' table (below) with data from my 'summary' table:
TESTMATCH TABLE
+------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+-------+
| match_id | int(11) | NO | PRI | NULL | |
| match_date | date | YES | | NULL | |
| ground | varchar(50) | YES | MUL | NULL | |
| homeTeam | varchar(100) | YES | MUL | NULL | |
| awayTeam | varchar(100) | YES | MUL | NULL | |
| matchResult | varchar(100) | YES | MUL | NULL | |
| manOfMatch | varchar(30) | YES | | NULL | |
| homeTeam_captain | int(10) | YES | MUL | NULL | |
| homeTeam_keeper | int(10) | YES | MUL | NULL | |
| awayTeam_captain | int(10) | YES | MUL | NULL | |
| awayTeam_keeper | int(10) | YES | MUL | NULL | |
+------------------+--------------+------+-----+---------+-------+
There is no problem populating match_id -----> manOfMatch - it is 'homeTeam_captain', 'homeTeam_keeper', 'awayTeam_captain' and 'awayTeam_keeper' that i'm having problems bringing in.
SUMMARY TABLE
mysql> DESCRIBE SUMMARY;
+-----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+-------+
| matchID | int(11) | NO | PRI | NULL | |
| Test | int(11) | YES | | NULL | |
| matchDate | date | YES | | NULL | |
| Ground | varchar(50) | YES | | NULL | |
| HomeTeam | varchar(100) | YES | | NULL | |
| AwayTeam | varchar(100) | YES | | NULL | |
| matchResult | varchar(50) | YES | | NULL | |
| MarginRuns | int(11) | YES | | NULL | |
| MarginWickets | int(11) | YES | | NULL | |
| ManOfMatch | varchar(40) | YES | | NULL | |
| HomeTeamCaptain | varchar(30) | YES | | NULL | |
| HomeTeamKeeper | varchar(30) | YES | | NULL | |
| AwayTeamCaptain | varchar(30) | YES | | NULL | |
| AwayTeamKeeper | varchar(30) | YES | | NULL | |
+-----------------+--------------+------+-----+---------+-------+
I need to somehow select the data from summary, get the corresponding player_id and input the player_id into my 'testMatch'. Player table below:
PLAYERS TABLE
mysql> describe players;
+----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+----------------+
| player_id | int(11) | NO | PRI | NULL | auto_increment |
| player_surname | varchar(30) | YES | | NULL | |
| team | varchar(100) | YES | MUL | NULL | |
+----------------+--------------+------+-----+---------+----------------+
So to clarify, eg. I want to select homeTeam_captain data FROM summary table BUT not the name, I want the corresponding player_id instead.
I assume I need to use some sort of join/subqueries to get this done... i've tried finding the correct select query first to make sure i'm pulling out the right data, and I have been using the below code for testing (thanks to user Larry_Croft for helping me with this):
select matchID, player_id, player_surname, team from players p, summary s
where
s.hometeamcaptain = p.player_surname AND s.HomeTeam = p.team ORDER BY matchID;
But this correctly brings back 65 rows (65 matches) BUT i then tried it with:
select matchID, player_id, player_surname, team from players p, summary s
where
s.hometeamKEEPER = p.player_surname AND s.HomeTeam = p.team ORDER BY matchID;
But this brings back only 61 rows (should be 65) so i must have an error in the logic.
Once I get this select to work, i then need to somehow include it into my 'INSERT INTO.....SELECT statement to put all the data into 'testMatch' table.
I hope this makes sense and thanks for your help!
Well for me it looks that there is eitehr a hometeamKEEPER that has a null value or that the value of hometeamKEEPER is not in the players table.
Using the following query you should be able to find the hometownKEEPER that are not in the players table:
SELECT matchID, player_id, player_surname, team
FROM players p
RIGHT JOIN summary s ON p.hometeamKEEPER = p.player_surname AND
s.HomeTeam = p.team
ORDER BY matchID;