I currently have the below query that uses a UNION join to connect two queries and SQL variables to alternate the order the rows are shown between sum of numbers and count of activities. When I add the SET lines to the query the PHP file has an error and when I remove them the query runs but no values are retrieved. I've run the query on the server and it works.
How do I use SQL variables in the prepared statement? If it's not possible how would I rewrite the query to get the same outcome?
SET #a = 0;
SET #b = 0;
SELECT * FROM(
SELECT #a := #a + 1 AS sortOne, 1 AS sortTwo, tbl_company.comp_name AS comp_name, tbl_shift.shift_name AS shift_name,
SUM(tbl_short_term_programme.sun_p) AS sun_p_total, SUM(tbl_short_term_programme.sun_a) AS sun_a_total,
SUM(tbl_short_term_programme.mon_p) AS mon_p_total, SUM(tbl_short_term_programme.mon_a) AS mon_a_total,
SUM(tbl_short_term_programme.tue_p) AS tue_p_total, SUM(tbl_short_term_programme.tue_a) AS tue_a_total,
SUM(tbl_short_term_programme.wed_p) AS wed_p_total, SUM(tbl_short_term_programme.wed_a) AS wed_a_total,
SUM(tbl_short_term_programme.thu_p) AS thu_p_total, SUM(tbl_short_term_programme.thu_a) AS thu_a_total,
SUM(tbl_short_term_programme.fri_p) AS fri_p_total, SUM(tbl_short_term_programme.fri_a) AS fri_a_total,
SUM(tbl_short_term_programme.sat_p) AS sat_p_total, SUM(tbl_short_term_programme.sat_a) AS sat_a_total
FROM tbl_short_term_programme
INNER JOIN tbl_phase ON tbl_short_term_programme.phase_id = tbl_phase.phase_id
INNER JOIN tbl_company ON tbl_short_term_programme.company_id = tbl_company.company_id
INNER JOIN tbl_shift ON tbl_short_term_programme.shift_id = tbl_shift.shift_id
WHERE tbl_phase.phase_hash = ? AND YEARWEEK(tbl_short_term_programme.short_term_date, 2) = YEARWEEK(?, 2)
GROUP BY tbl_shift.shift_id, tbl_company.comp_name
UNION
SELECT #b := #b + 1 AS sortOne, 2 AS sortTwo, tbl_company.comp_name AS comp_name, tbl_shift.shift_name AS shift_name,
COUNT(tbl_short_term_programme.sun_p) AS sun_p_total, COUNT(tbl_short_term_programme.sun_a) AS sun_a_total,
COUNT(tbl_short_term_programme.mon_p) AS mon_p_total, COUNT(tbl_short_term_programme.mon_a) AS mon_a_total,
COUNT(tbl_short_term_programme.tue_p) AS tue_p_total, COUNT(tbl_short_term_programme.tue_a) AS tue_a_total,
COUNT(tbl_short_term_programme.wed_p) AS wed_p_total, COUNT(tbl_short_term_programme.wed_a) AS wed_a_total,
COUNT(tbl_short_term_programme.thu_p) AS thu_p_total, COUNT(tbl_short_term_programme.thu_a) AS thu_a_total,
COUNT(tbl_short_term_programme.fri_p) AS fri_p_total, COUNT(tbl_short_term_programme.fri_a) AS fri_a_total,
COUNT(tbl_short_term_programme.sat_p) AS sat_p_total, COUNT(tbl_short_term_programme.sat_a) AS sat_a_total
FROM tbl_short_term_programme
INNER JOIN tbl_phase ON tbl_short_term_programme.phase_id = tbl_phase.phase_id
INNER JOIN tbl_company ON tbl_short_term_programme.company_id = tbl_company.company_id
INNER JOIN tbl_shift ON tbl_short_term_programme.shift_id = tbl_shift.shift_id
WHERE tbl_phase.phase_hash = ? AND YEARWEEK(tbl_short_term_programme.short_term_date, 2) = YEARWEEK(?, 2)
GROUP BY tbl_shift.shift_id, tbl_company.comp_name
) AS result ORDER BY sortOne, sortTwo
$stmt->bind_param("ssss", $phase_hash, $formatted_date, $phase_hash, $formatted_date);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($comp_name, $shift_name, $sun_p_total, $sun_a_total, $mon_p_total, $mon_a_total, $tue_p_total,
$tue_a_total, $wed_p_total, $wed_a_total, $thu_p_total, $thu_a_total, $fri_p_total, $fri_a_total,
$sat_p_total, $sat_a_total);
$row_array = array();
while($stmt->fetch()) {
$tmp = array();
$tmp["shift_name"] = $shift_name;
$tmp["comp_name"] = $comp_name;
$tmp["sun_p_total"] = $sun_p_total;
$tmp["sun_a_total"] = $sun_a_total;
$tmp["mon_p_total"] = $mon_p_total;
$tmp["mon_a_total"] = $mon_a_total;
$tmp["tue_p_total"] = $tue_p_total;
$tmp["tue_a_total"] = $tue_a_total;
$tmp["wed_p_total"] = $wed_p_total;
$tmp["wed_a_total"] = $wed_a_total;
$tmp["thu_p_total"] = $thu_p_total;
$tmp["thu_a_total"] = $thu_a_total;
$tmp["fri_p_total"] = $fri_p_total;
$tmp["fri_a_total"] = $fri_a_total;
$tmp["sat_p_total"] = $sat_p_total;
$tmp["sat_a_total"] = $sat_a_total;
array_push($row_array, $tmp);
}
$stmt->close();
echo json_encode($row_array);
As Bill Karwin said, you can only run one query in a prepared statement. Another way to solve it is to assign the variables in a subquery that you join with the main query.
SELECT * FROM(
SELECT #a := #a + 1 AS sortOne, 1 AS sortTwo, tbl_company.comp_name AS comp_name, tbl_shift.shift_name AS shift_name,
SUM(tbl_short_term_programme.sun_p) AS sun_p_total, SUM(tbl_short_term_programme.sun_a) AS sun_a_total,
SUM(tbl_short_term_programme.mon_p) AS mon_p_total, SUM(tbl_short_term_programme.mon_a) AS mon_a_total,
SUM(tbl_short_term_programme.tue_p) AS tue_p_total, SUM(tbl_short_term_programme.tue_a) AS tue_a_total,
SUM(tbl_short_term_programme.wed_p) AS wed_p_total, SUM(tbl_short_term_programme.wed_a) AS wed_a_total,
SUM(tbl_short_term_programme.thu_p) AS thu_p_total, SUM(tbl_short_term_programme.thu_a) AS thu_a_total,
SUM(tbl_short_term_programme.fri_p) AS fri_p_total, SUM(tbl_short_term_programme.fri_a) AS fri_a_total,
SUM(tbl_short_term_programme.sat_p) AS sat_p_total, SUM(tbl_short_term_programme.sat_a) AS sat_a_total
FROM tbl_short_term_programme
INNER JOIN tbl_phase ON tbl_short_term_programme.phase_id = tbl_phase.phase_id
INNER JOIN tbl_company ON tbl_short_term_programme.company_id = tbl_company.company_id
INNER JOIN tbl_shift ON tbl_short_term_programme.shift_id = tbl_shift.shift_id
CROSS JOIN (SELECT #a := 0) AS var
WHERE tbl_phase.phase_hash = ? AND YEARWEEK(tbl_short_term_programme.short_term_date, 2) = YEARWEEK(?, 2)
GROUP BY tbl_shift.shift_id, tbl_company.comp_name
UNION
SELECT #b := #b + 1 AS sortOne, 2 AS sortTwo, tbl_company.comp_name AS comp_name, tbl_shift.shift_name AS shift_name,
COUNT(tbl_short_term_programme.sun_p) AS sun_p_total, COUNT(tbl_short_term_programme.sun_a) AS sun_a_total,
COUNT(tbl_short_term_programme.mon_p) AS mon_p_total, COUNT(tbl_short_term_programme.mon_a) AS mon_a_total,
COUNT(tbl_short_term_programme.tue_p) AS tue_p_total, COUNT(tbl_short_term_programme.tue_a) AS tue_a_total,
COUNT(tbl_short_term_programme.wed_p) AS wed_p_total, COUNT(tbl_short_term_programme.wed_a) AS wed_a_total,
COUNT(tbl_short_term_programme.thu_p) AS thu_p_total, COUNT(tbl_short_term_programme.thu_a) AS thu_a_total,
COUNT(tbl_short_term_programme.fri_p) AS fri_p_total, COUNT(tbl_short_term_programme.fri_a) AS fri_a_total,
COUNT(tbl_short_term_programme.sat_p) AS sat_p_total, COUNT(tbl_short_term_programme.sat_a) AS sat_a_total
FROM tbl_short_term_programme
INNER JOIN tbl_phase ON tbl_short_term_programme.phase_id = tbl_phase.phase_id
INNER JOIN tbl_company ON tbl_short_term_programme.company_id = tbl_company.company_id
INNER JOIN tbl_shift ON tbl_short_term_programme.shift_id = tbl_shift.shift_id
CROSS JOIN (SELECT #b :- 0) AS var
WHERE tbl_phase.phase_hash = ? AND YEARWEEK(tbl_short_term_programme.short_term_date, 2) = YEARWEEK(?, 2)
GROUP BY tbl_shift.shift_id, tbl_company.comp_name
) AS result ORDER BY sortOne, sortTwo
By default, you can only run one SQL statement per call to mysqli_prepare().
I suggest setting the session variables in a separate statement:
$mysqli->query("set #a = 0, #b = 0");
Then do your prepare & execute of your big query.
Some people might tell you to use the mysqli_multi_query() function, but you can't because it doesn't support prepared statements.
It's okay though, there's no advantage to doing multiple queries in a single call. Just set your variables in one call and then do the prepared statement subsequently. As long as you use the same db connection, the session variables will still have their values.
Related
I am using the MySQL build-in operators to get a running total, the query works well when I run it in phpMyAdmin, but running it in php does not work, I just get the "Couldn't execute query" message.
My database connection works fine, thus can I do this in php or is there another way to get this to work?
Here is the script:
include("../../include/xxx.inc");
$cxn = mysqli_connect($host,$user,$password,$dbname);
$query = "SET #runtot:=0;
SELECT `q1`.`c`, (#runtot := #runtot + `q1`.`c`) AS rt
FROM (
SELECT SUM( `sr`.`sr_qty` * `st`.`st_ton` ) AS c, `sr`.`sr_no`
FROM `sr`
JOIN `st` ON `sr`.`st_code` = `st`.`st_code`
WHERE `sr`.`sr_date` BETWEEN '2015-01-15' AND '2015-02-15'
GROUP BY `sr`.`sr_no`
ORDER BY `sr`.`sr_no`) AS q1";
$result = mysqli_query($cxn,$query)
or die ("Couldn't execute query.");
while($row = mysqli_fetch_assoc($result))
{
extract($row);
echo "$rt Ton";
Try setting the variable inside the query, so you only have one statement:
SELECT `q1`.`c`, (#runtot := #runtot + `q1`.`c`) AS rt
FROM (
SELECT SUM( `sr`.`sr_qty` * `st`.`st_ton` ) AS c, `sr`.`sr_no`
FROM (SELECT #runtst := 0) vars cross join
`sr`
JOIN `st` ON `sr`.`st_code` = `st`.`st_code`
WHERE `sr`.`sr_date` BETWEEN '2015-01-15' AND '2015-02-15'
GROUP BY `sr`.`sr_no`
ORDER BY `sr`.`sr_no`) AS q1
I'm not completely sure, but i think it's all your `'s
i would do SELECT 'q2.c', (# an so on.
But again, i might be wrong, but it's something to try.
You can't run multiple queries with mysqli_query. You need to call it separately for each query:
$query1 = "SET #runtot:=0"
$query2 = "SELECT `q1`.`c`, (#runtot := #runtot + `q1`.`c`) AS rt
FROM (
SELECT SUM( `sr`.`sr_qty` * `st`.`st_ton` ) AS c, `sr`.`sr_no`
FROM `sr`
JOIN `st` ON `sr`.`st_code` = `st`.`st_code`
WHERE `sr`.`sr_date` BETWEEN '2015-01-15' AND '2015-02-15'
GROUP BY `sr`.`sr_no`
ORDER BY `sr`.`sr_no`) AS q1";
mysqli_query($query1);
$result = mysqli_query($query2);
You can also put variable initializations into a subquery:
$query = "SELECT `q1`.`c`, (#runtot := #runtot + `q1`.`c`) AS rt
FROM (
SELECT SUM( `sr`.`sr_qty` * `st`.`st_ton` ) AS c, `sr`.`sr_no`
FROM `sr`
JOIN `st` ON `sr`.`st_code` = `st`.`st_code`
WHERE `sr`.`sr_date` BETWEEN '2015-01-15' AND '2015-02-15'
GROUP BY `sr`.`sr_no`
ORDER BY `sr`.`sr_no`) AS q1
CROSS JOIN (SELECT #runtot := 0) AS init";
mysqli also has mysqli_multi_query, which allows running multiple queries, but I've seen too many people run into problems to recommend it. It's rarely needed, IMHO.
This is my native query:
$query = <<<Query
SET #num = 0;
SET #type = 0;
SELECT md.*, od.id AS order_detail_id, od.erc AS od_ec,
#num := if(#type = od.id, #num + 1, 1) AS row_number,
#type := od.id AS dummy
FROM bar md
LEFT JOIN foobar mb ON md.mbi = mb.id
LEFT JOIN barfoo od ON od.mbid = mb.id
WHERE od.id IN ($where)
AND (od.status = $statusQueued OR od.status = $statusProcessing)
GROUP BY md.id
HAVING row_number <= od.erc
ORDER BY md.qt ASC
LIMIT 0, 1000
Query;
$nativeQuery = $this->_em->createNativeQuery($query, $rsm);
When I execute it, PDO gets upset and throws me an error:
[PDOException] SQLSTATE[HY000]: General error
No more informations.
However when I get rid of first two lines (with "SET") the query runs (however returns wrong results, as the variables must be initialised in this case). How can I force PDO to run this correctly? (when run via PMA it works just fine)
It seems that most elegant solution is to leverage MySQL alternative initialisation syntax:
$query = <<<Query
SELECT md.*, od.id AS order_detail_id, od.erc AS od_ec,
#num := if(#type = od.id, #num + 1, 1) AS row_number,
#type := od.id AS dummy
FROM (SELECT #num := 0, #type := 0) init, bar md
LEFT JOIN foobar mb ON md.mbi = mb.id
LEFT JOIN barfoo od ON od.mbid = mb.id
WHERE od.id IN ($where)
AND (od.status = $statusQueued OR od.status = $statusProcessing)
GROUP BY md.id
HAVING row_number <= od.erc
ORDER BY md.qt ASC
LIMIT 0, 1000
Query;
I ran into the same kind of issue trying to run several queries in one call (in my case it was about using SQL_CALC_FOUND_ROWS and its buddy FOUND_ROWS()).
Doctrine can't handle this. I don't know the official reason, but in my opinion it's probably a security concern (as the EM's calls are then open to basic query injection).
Still in my opinion, the most elegant way of dealing with this is using the EM's transactional mode:
//fetch PDO-ish adapter
$conn = $em->getConnection();
//open an atomic sequence
$conn->beginTransaction();
//do your stuff
$conn->executeQuery('SET #...');
$stmt = $conn->executeQuery('SELECT stuff using #vars');
//commit the atomic sequence
$conn->commit();
//fetch the result, could be useful ;)
$data = $conn->fetchAll();
Hope this helps! (and works in your case...)
function sum($nomId){
$sql = "SELECT SUM(nomDetCantidad) FROM table2 where Id = $nomId";
$Resultado=$this->ProcesaSQLQueryList($sql);
if($Resultado>0){
foreach($Resultado as $key => $valor){
$cantidadTotal = $valor[0];
}
}
if($Resultado=='null'){$cantidadTotal=0;}
$sql = "UPDATE table1 SET nomCantidadTotal=$cantidadTotal,nomActualizado = NOW() WHERE nomId= $nomId";
return $this->ProcesaSQLQueryUpdate($sql);
and this is the function I call
function ProcesaSQLQueryList($SQLQuery){
$row= array();
if(!$this->link_mysql) $this->link_mysql = conectarManager();
if($res = mysql_query($SQLQuery,$this->link_mysql)){
while($r = mysql_fetch_array($res)){
$row[] = $r;
}
mysql_free_result($res);
return $row;
}else{
$this->last_error = $SQLQuery . " - " . mysql_error();
return -1;
}
}
So I sum up whatever I have in a field table 2 with the foreign key of table 1 then my result gets updated to the table 1 field but if I delete the fields in table 2 result wont get updated to 0 any suggestions I'm pretty sure this is an easy one but can't seem to find it
$sql = "SELECT SUM(nomDetCantidad) FROM table2 where nominaId = $nomId";
$Resultado = $this->ProcesaSQLQueryList($sql);
if ($Resultado > 0) {
foreach ($Resultado as $key => $valor) {
$cantidadTotal = $valor[0];
}
}
if ($cantidadTotal == '') {
$cantidadTotal=0.00;
}
$sql = "UPDATE table1 SET nomCantidadTotal=$cantidadTotal,nomActualizado = NOW() WHERE nomId = $nomId";
return $this->ProcesaSQLQueryUpdate($sql);
There! It was sending me a blank variable xD but fixed and there are more suitable ways to do it, I agree with Spencer but if a client wants a red swing he has to get a red swing you know? :) thanks for the help guys!
If you need a zero returned when there are no "matching" rows in table2, then wrap the return expression in an IFNULL function.
SELECT IFNULL(SUM(nomDetCantidad),0) FROM table2 ...
You could significantly reduce the amount of code you have, reduce the number of roundtrips to the database, and improve performance by doing all this work in a single UPDATE statement. You can use either a correlated subquery or an OUTER JOIN:
-- using a correleated subquery
UPDATE table t1
SET t1.nomActualizado = NOW()
, t1.nomCantidadTotal =
( SELECT IFNULL(SUM(t2.nomDetCantidad),0) AS nomCantidadTotal
FROM table2 t2
WHERE t2.Id = t1.nomID
)
WHERE t1.nomId = $nomId
-- using an OUTER JOIN
UPDATE table1 t1
LEFT
JOIN (SELECT t2.Id, SUM(t2.nomDetCantidad) AS nomCantidadTotal
FROM table2 t2
WHERE t2.Id = $nomId
GROUP BY t2.Id
) s
ON s.Id = t1.nomID
SET t1.nomCantidadTotal = IFNULL(s.nomCantidadTotal,0)
, t1.nomActualizado = NOW()
WHERE t1.nomID = $nomId
It's not at all clear why you need to store this total on table1, when you could derive it from table2 whenever you need it, without storing that value on table1 at all...
SELECT t1.nomId
, IFNULL((SELECT SUM(t2.nomDetCantidad) AS nomCantidadTotal
FROM table2 t2
WHERE t2.Id = t1.nomID
),0) AS nomCantidadTotal
FROM table1 t1
WHERE t1.nomId = $nomId
I'm using Msqli to make a multiquery, the query works exactly like i want within phpmyadmin.
it do not work with mysqli anymore. The query did not change between servers.
The query below Was working in a previous LAMP installation but not in the current.
$SQLquery ='set #type = \'\';
set #num = 1;
SELECT
RA.`DATE` as DATES,
RA.`ADDR` as ADDR,
RA.`QID` as QID,
RT.`TAGS` as TAG,
Q.`id` AS QUID,
Q.`ADDR` AS QADDR,
Q.`ORIGINALTEXT` AS QTEXTS,
Q.`DATE` AS QDATES,
cs.`id` AS CUID,
cs.`ADDR` AS CADDR,
cs.`ORIGINALTEXT` AS CTEXTS,
cs.`DATE` AS CDATES,
sol.`id` AS SUID,
sol.`ORIGINALTEXT` AS STEXTS,
sol.`ADDR` AS SADDR,
sol.`DATE` AS SDATES,
prj.`id` AS PUID,
prj.`ORIGINALTEXT` AS PTEXTS,
prj.`ADDR` AS PADDR,
prj.`DATE` AS PDATES,
Max(Q.`DATE` ) AS Q,
Max(cs.`DATE` ) AS C,
Max(sol.`DATE` ) AS S,
Max(prj.`DATE` ) AS P,
##num as row_number
#num:= if(#type = RA.`ADDR`, 1+#num, 1) as v_number,
#type := RA.`ADDR` as dummy
FROM (SELECT `id`,`TAGS`, `QID` from `REL_TAG` ) AS RT
inner Join (SELECT `DATE`, `ADDR`, `QID` from `REL_ADDR` order by DATE) AS RA ON ( RT.`QID` = RA.`QID`)
Left outer Join (SELECT `id`,`DATE`, `ADDR`, `QID`, `ORIGINALTEXT` FROM `QUESTION`) AS Q ON ( RT.`QID` = Q.`QID`) and Q.`ADDR` = RA.`ADDR`
Left outer Join (SELECT `id`,`DATE`, `ADDR`, `QID`, `ORIGINALTEXT` FROM `CASES` order by `CASES`.`DATE`) AS cs ON ( RT.`QID` = cs.`QID`) and cs.`ADDR` = RA.`ADDR`
Left outer Join (SELECT `id`,`DATE`, `ADDR`, `QID`, `ORIGINALTEXT` FROM `SOLUTION` order by `SOLUTION`.`DATE`) AS sol ON ( RT.`QID` = sol.`QID`) and sol.`ADDR` = RA.`ADDR`
Left outer Join (SELECT `id`,`DATE`, `ADDR`, `QID`, `ORIGINALTEXT` FROM `PROJECT` order by `PROJECT`.`DATE`) AS prj ON ( RT.`QID` = prj.`QID`) and prj.`ADDR` = RA.`ADDR`
where RT.`QID` = \''.NbOnly($Fetchmodifier).'\' Group by `QID`, addr, v_number LIMIT '.$Anstart.' ,'.$Ansnb.';';
Update
The query does not return any error in the logs, it just return nothing (null).
Here is the PHP code to execute the MySQLi Multiquery
$mysqlin = new mysqli("localhost", "user", "pass", "db");
if (mysqli_error($mysqlin)) {
outputdataXML(sprintf("Connect Problem : %s\n", mysqli_error($mysqlin)));
exit();
}
if ($mysqlin->multi_query($SQLquery)) {
do {
if ($result = $mysqlin->store_result()) {
while ($row = $result->fetch_array(MYSQLI_BOTH)) {
if( $Foundrows = $row[0]){ //Maybe the problem is here ?
$Outputvalue[] = FormatFile($row);
}
}
$result->free();
}
if ($mysqlin->more_results()) {
}
} while ($mysqlin->more_results() && $mysqlin->next_result());
}
$mysqlin->close();
I have Found the problem, Some but not all of the tables Were EMPTY,
As in Without any records,
I added a dummy record To each tables, some tables had records but some were without,
and now even if the Query dont matchThe joins are Now still being Made properly.
I Hope this help lots of ppl.
When your using MySQL "Join", you need 1 record in each and All of your joined tables, no matter if it will ever be used ex: 0, 00-00-0000, Null , 0, empty
Only then, all the joinning Tables included in the query will work.
The following MySQL query runs in PHP without errors, but the resultset is empty. Directly outputting the query string to a file and running the query in the MySQL client using 'source [filename]' returns several rows of results, as expected.
Is there something that would cause this query not to work with PHP? categorylinks.cl_to and smw_spec2.value_string are both varbinary(255). Show create table indicates engine=InnoDB and default charset=binary.
Things I have tried without success:
$sql = preg_replace("/[\n\t]+/", " ", $sql);
Changing '_wpg' and 'Derp' to CAST('_wpg' AS BINARY(255))
Changing '_wpg' and 'Derp' to BINARY '_wpg'
I am using the MediaWiki DatabaseMysql class to execute the query and fetch rows, but it's a very thin abstraction, and I'm certain it's not the problem (see below).
SELECT
prop.name AS prop_name, prop.count AS prop_count, prop.type AS prop_type,
val.value AS val_value, val.unit AS val_unit, val.count AS val_count
FROM
(
SELECT
s_id, name, type, COUNT(foo.name) AS count
FROM (
(
SELECT
cl.cl_to AS cat_name, s.smw_id AS s_id, s.smw_sortkey AS name, spec.value_string AS type
FROM `smw_ids` s
INNER JOIN (`categorylinks` cl, `page` p, `smw_ids` s2, `smw_atts2` a)
ON (cl.cl_from = p.page_id AND
p.page_title = s2.smw_title AND
s2.smw_id = a.s_id AND
a.p_id = s.smw_id)
LEFT JOIN `smw_spec2` spec ON s.smw_id = spec.s_id
)
UNION ALL
(
SELECT
cl.cl_to AS cat_name, s.smw_id AS s_id, s.smw_sortkey AS name, '_wpg' AS type
FROM `smw_ids` s
INNER JOIN (`categorylinks` cl, `page` p, `smw_ids` s2, `smw_rels2` a)
ON (cl.cl_from = p.page_id AND
p.page_title = s2.smw_title AND
s2.smw_id = a.s_id AND
a.p_id = s.smw_id)
)
) AS foo
WHERE foo.cat_name = 'Derp'
GROUP BY name
ORDER BY count DESC
LIMIT 10
) AS prop
INNER JOIN
(
SELECT
bar.p_id AS p_id, bar.value AS value, bar.unit AS unit, COUNT(bar.value) AS count,
IF( #prev != p_id, #rownum := 1, #rownum := #rownum+1 ) AS rank,
#prev := p_id
FROM (
(SELECT a.p_id AS p_id, a.value_xsd AS value, a.value_unit AS unit FROM `smw_atts2` a)
UNION ALL
(SELECT r.p_id AS p_id, s.smw_sortkey AS value, NULL AS unit
FROM `smw_rels2` r INNER JOIN `smw_ids` s ON r.o_id = s.smw_id)
) AS bar
GROUP BY value, unit
ORDER BY count DESC
) AS val
ON prop.s_id = val.p_id
WHERE val.rank <= 50
ORDER BY prop_count DESC, prop_name, val_count DESC, val_value
Edit: The following test script outputs nothing. query.sql contains exactly the query above, written to file immediately preceding the mysql_query() call in MediaWiki's database class.
$db = mysql_connect('localhost', 'root', '');
mysql_select_db('mediawiki', $db);
$res = mysql_query(file_get_contents("query.sql"), $db);
while ($row = mysql_fetch_assoc($res)) {
var_dump($row);
}
echo mysql_error($db);
Edit: I imported a huge database dump and afterwards, when I loaded the PHP page, there was a noticeable wait that seemed to indicate that the query was running, but still no results showed. I ended up reworking the query, and I no longer have this problem.
Try this to detect and report errors better:
$db = mysql_connect('localhost', 'root', '');
mysql_select_db('mediawiki', $db);
$res = mysql_query(file_get_contents("query.sql"), $db);
if (!$res) {
print "SQL Error ".mysql_errno().":".mysql_error().", from query: '".file_get_contents("query.sql")."'";
} else {
while ($row = mysql_fetch_assoc($res)) {
var_dump($row);
}
}
Try this after mysql_connect:
mysql_query('SET NAMES utf8;');