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.
Related
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 |
+-----+--------+------------------+---------------+-----------+----------+----------+
I'm trying to figure out why results returned via a MySQL terminal query don't match those returned by a MySQL query executed by PHP.
Here's the MySQL used in the shell:
SELECT * FROM SANKEY_NODE AS n
LEFT OUTER JOIN TYPE_DETAIL as td
ON n.TYPE_DETAIL_ID = td.TYPE_DETAIL_ID
LEFT OUTER JOIN GRAPH_TYPE as t
ON td.GRAPH_TYPE_ID = t.GRAPH_TYPE_ID
WHERE CHART_ID = 39;
Here's the PHP:
function get_nodes_by_chart_id($con, $chart_id) {
$sql = 'SELECT * FROM SANKEY_NODE AS n
LEFT OUTER JOIN TYPE_DETAIL as td
ON n.TYPE_DETAIL_ID = td.TYPE_DETAIL_ID
LEFT OUTER JOIN GRAPH_TYPE as t
ON td.GRAPH_TYPE_ID = t.GRAPH_TYPE_ID
WHERE CHART_ID = '.$chart_id.';';
$result = mysqli_query($con, $sql);
return results_to_array($result);
}
function results_to_array($results) {
$rows = array();
while($row = mysqli_fetch_assoc($results)) {
$rows[] = $row;
}
return $rows;
}
Both queries return a dozen results, however, they differ in their representation of three results. Those three results are special because they have a TYPE_DETAIL_ID value in the SANKEY_NODE table that is not present in the TYPE_DETAIL table.
In the MySQL shell, the TYPE_DETAIL_ID value for the three affected nodes is displayed, whereas in the results returned by PHP, the TYPE_DETAIL_ID value is null. Does anyone know what might cause this difference? I'd be very grateful for any insight others can offer!
Table Structures
mysql> describe SANKEY_NODE;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| NODE_NAME | varchar(100) | NO | | NULL | |
| NODE_PARENT | varchar(20) | YES | | NULL | |
| CHART_ID | int(11) | NO | PRI | NULL | |
| NODE_TYPE | varchar(100) | NO | | NULL | |
| TYPE_DETAIL_ID | varchar(20) | NO | PRI | NULL | |
+----------------+--------------+------+-----+---------+-------+
mysql> describe TYPE_DETAIL;
+------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+-------+
| COMPANY_ID | int(11) | NO | | NULL | |
| GRAPH_TYPE_ID | int(11) | NO | PRI | NULL | |
| TYPE_DETAIL_CD | varchar(20) | NO | PRI | NULL | |
| TYPE_DETAIL_NAME | varchar(100) | NO | | NULL | |
| TYPE_DETAIL_DESC | varchar(200) | YES | | NULL | |
| TYPE_DETAIL_ID | int(11) | NO | | NULL | |
| TYPE_IMAGE_ID | int(11) | YES | | NULL | |
| ACTIVE_FLAG | bit(1) | NO | | NULL | |
+------------------+--------------+------+-----+---------+-------+
mysql> describe GRAPH_TYPE;
+----------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+--------------+------+-----+---------+----------------+
| COMPANY_ID | int(11) | NO | PRI | NULL | |
| GRAPH_TYPE_ID | int(11) | NO | UNI | NULL | auto_increment |
| TYPE_CD | varchar(20) | NO | PRI | NULL | |
| TYPE_NAME | varchar(100) | NO | | NULL | |
| TYPE_COLOR | varchar(50) | NO | | NULL | |
| TYPE_HIGHLIGHT_COLOR | varchar(50) | NO | | NULL | |
| ACTIVE_FLAG | bit(1) | NO | | NULL | |
+----------------------+--------------+------+-----+---------+----------------+
Comment Responses
#Cedric, running the query with just the first JOIN yields the same results. The three values whose TYPE_DETAIL_ID is present in SANKEY_NODE but not in TYPE_DETAIL_ID have a defined TYPE_DETAIL_ID in the shell results but not in the results via PHP (see results below). As for syntax, I'm a fan of the philosophy that "explicit is better than implicit".
#jcaron, the TYPE_DETAIL_ID values are either sequences of integers or ascii strings, e.g.:
mysql> SELECT * FROM SANKEY_NODE AS n LEFT OUTER JOIN TYPE_DETAIL as td ON n.TYPE_DETAIL_ID = td.TYPE_DETAIL_ID WHERE CHART_ID = 3;
+--------------------------+-------------+----------+-------------+----------------+------------+---------------+----------------+--------------------+--------------------+----------------+---------------+-------------+
| NODE_NAME | NODE_PARENT | CHART_ID | NODE_TYPE | TYPE_DETAIL_ID | COMPANY_ID | GRAPH_TYPE_ID | TYPE_DETAIL_CD | TYPE_DETAIL_NAME | TYPE_DETAIL_DESC | TYPE_DETAIL_ID | TYPE_IMAGE_ID | ACTIVE_FLAG |
+--------------------------+-------------+----------+-------------+----------------+------------+---------------+----------------+--------------------+--------------------+----------------+---------------+-------------+
| CRD | SYS | 3 | System | 101004 | 7777 | 1 | CRD | Charles River | Charles River | 101004 | NULL | |
| FactSet | SYS | 3 | System | 101012 | 7777 | 1 | FACTSET | Factset | Factset | 101012 | NULL | |
| MSCI | SYS | 3 | System | 101016 | 7777 | 1 | RISKMETRICS | MSCI RiskWorld | MSCI RiskWorld | 101016 | NULL | |
| Trade Execution | FUN | 3 | Function | 109007 | 7777 | 9 | TE | Trade Execution | Trade Execution | 109007 | NULL | |
| Portfolio Mgmt | FUN | 3 | Function | 109003 | 7777 | 9 | PM | Portfolio Mgmt | Portfolio Mgmt | 109003 | NULL | |
| Performance & Risk | FUN | 3 | Function | 109002 | 7777 | 9 | PMR | Performance & Risk | Performance & Risk | 109002 | NULL | |
| Operations | FUN | 3 | Function | 109006 | 7777 | 9 | OPS | Operations | Operations | 109006 | NULL | |
| Decision Making | FUN | 3 | Function | 109001 | 7777 | 9 | DM | Decision Making | Decision Making | 109001 | NULL | |
| Compliance | FUN | 3 | Function | 109005 | 7777 | 9 | COMP | Compliance | Compliance | 109005 | NULL | |
| Portfolio Rebalance | SFUN | 3 | SubFunction | 201091 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| Position Reconciliation | SFUN | 3 | SubFunction | 201092 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| PreTrade Compliance | SFUN | 3 | SubFunction | 201096 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| Step-outs | SFUN | 3 | SubFunction | 201109 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| Trade Matching | SFUN | 3 | SubFunction | 201125 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| Trade Settlement | SFUN | 3 | SubFunction | 201129 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| Functions | | 3 | Function | FUN | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| SubFunction | | 3 | SubFunction | SFUN | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| Systems | | 3 | System | SYS | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+--------------------------+-------------+----------+-------------+----------------+------------+---------------+----------------+--------------------+--------------------+----------------+---------------+-------------+
18 rows in set, 225 warnings (0.00 sec)
Here is an easy workaround, specify the table name for each column :
SELECT SANKEY_NODE.TYPE_DETAIL_ID FROM SANKEY_NODE AS n
That way, you will be sure to have the data that you expect
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.
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.
I'm trying to get the number of games that summoners in the queue have played today. I have tried several queries. The closest I have gotten is:
SELECT
s.summoner,
s.wins,
COUNT(*) as playedToday
FROM summoners s
LEFT JOIN teams_players tp ON tp.summoner_id = s.summoner
LEFT JOIN teams t ON t.id = tp.team_id
LEFT JOIN matches b ON t.id = b.blue_id
WHERE
b.played_on = DATE(NOW())
s.in_queue;
But that doesn't give the count per-user. It just gets the overall count.
None of the tables have any data on any of the summoners. What I'd like is something like:
+-----------------+------+-------------+
| summoner | wins | gamesPlayed |
+-----------------+------+-------------+
| DotAliscious | 353 | 0 |
| Kraator | 440 | 0 |
| Nammon | 667 | 0 |
| VictorousSecret | 843 | 0 |
| Canas | 544 | 0 |
| Sprognak | 502 | 0 |
| Ghostilocks | 808 | 0 |
| b0b d0e | 224 | 0 |
| Metroshica | 339 | 0 |
| RubenatorX | 478 | 0 |
+-----------------+------+-------------+
I can't think how to express this problem generically, which is why I haven't found a solution.
My data set. Note that teams.id matches up with matches.blue_id and matches.purple_id.
mysql> DESCRIBE summoners;
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| icon | int(11) | NO | | 0 | |
| summoner | varchar(32) | NO | UNI | NULL | |
| skype | varchar(32) | NO | | NULL | |
| email | varchar(32) | NO | | NULL | |
| in_queue | tinyint(1) | NO | | 0 | |
| wins | int(11) | NO | | 0 | |
| level | int(11) | NO | | 1 | |
| lan_wins | int(11) | NO | | 0 | |
| played_today | int(11) | NO | | 0 | |
+--------------+-------------+------+-----+---------+----------------+
10 rows in set (0.00 sec)
mysql> DESCRIBE matches;
+-----------+-------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| blue_id | int(11) | NO | MUL | NULL | |
| purple_id | int(11) | NO | MUL | NULL | |
| status | varchar(32) | NO | | display | |
| played_on | datetime | NO | | 2012-04-06 13:53:55 | |
+-----------+-------------+------+-----+---------------------+----------------+
5 rows in set (0.00 sec)
mysql> DESCRIBE teams;
+---------+-------------+------+-----+------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| outcome | varchar(32) | NO | | incomplete | |
+---------+-------------+------+-----+------------+----------------+
2 rows in set (0.00 sec)
mysql> DESCRIBE teams_players;
+-------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| team_id | int(11) | NO | MUL | NULL | |
| summoner_id | int(11) | NO | MUL | NULL | |
+-------------+---------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
You're going to want to use a subselect to get the count of records that meet the condition, and that will return you a 0 if the condition is false. Something along the lines of
(SELECT COUNT(*) FROM matches b WHERE b.blue_id = t.id AND b.played_on = DATE(NOW())) AS playedToday
and you will want to remove the LEFT JOIN to the matches table and the WHERE clause checking the date.
Your played_on is datetime and you are comparing it with date maybe that's your problem. YOu should try:
WHERE
DATE(b.played_on) = DATE(NOW())
Also what do you mean by s.in_queue? Did you forget the AND? Do you mean
WHERE
DATE(b.played_on) = DATE(NOW())
AND
s.in_queue;