Reputation: 22275
I have the following MySql tables.
Table tblUsg
defined as such:
CREATE TABLE `tblUsg` (
`id` INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`ip` VARCHAR(46) NOT NULL,
`dtm` DATETIME NOT NULL,
`huid` BINARY(32) NOT NULL,
`licnm` VARCHAR(20) NOT NULL,
`lichld` VARCHAR(256) NOT NULL,
`flgs` INT NOT NULL,
`agnt` VARCHAR(256),
INDEX `ix_huid` (`huid`),
INDEX `ix_licnm` (`licnm`),
UNIQUE KEY `ix_lichuid` (`huid`, `licnm`)
) AUTO_INCREMENT=0 CHARACTER SET utf8 COLLATE utf8_unicode_ci;
And table tblLics
defined as such:
CREATE TABLE `wosLics` (
`id` INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`licnm` VARCHAR(20) NOT NULL,
`desc` VARCHAR(256) NOT NULL,
`maxcpy` INT NOT NULL,
`dtmFrom` DATETIME,
`dtmTo` DATETIME,
`stat` INT NOT NULL,
UNIQUE KEY `ix_licnm` (`licnm`)
) AUTO_INCREMENT=0 CHARACTER SET utf8 COLLATE utf8_unicode_ci;
I then call the following PHP script when, say, both tables are empty:
$link = @mysql_connect($HOSTNAME, $USERNAME, $PASSWD);
@mysql_select_db($DBNAME);
mysql_set_charset('utf8', $link);
$res = @mysql_query(
"SELECT `maxcpy`, `stat`, `dtmFrom`, `dtmTo` FROM `tblLics` WHERE `licnm`='zbcdefghijklmnopqrsu'\n".
"UNION ALL\n".
"SELECT COUNT(*), NULL, NULL, NULL FROM `tblUsg` WHERE `licnm`='zbcdefghijklmnopqrsu'\n".
"UNION ALL\n".
"SELECT COUNT(*), NULL, NULL, NULL FROM `tblUsg` WHERE (`licnm`='zbcdefghijklmnopqrsu' AND `huid`='a871c47a7f48a12b38a994e48a9659fab5d6376f3dbce37559bcb617efe8662d')"
, $link);
if($res)
{
$row0 = @mysql_fetch_row($res);
$row1 = @mysql_fetch_row($res);
$row2 = @mysql_fetch_row($res);
echo("<br/>0::<br/>");
var_dump($row0);
echo("<br/>1::<br/>");
var_dump($row1);
echo("<br/>2::<br/>");
var_dump($row2);
}
Which outputs this:
0::
array(4) { [0]=> string(1) "0" [1]=> NULL [2]=> NULL [3]=> NULL }
1::
array(4) { [0]=> string(1) "0" [1]=> NULL [2]=> NULL [3]=> NULL }
2::
bool(false)
My question is why my $row2
is false
when $row1
is the array as I would've expected?
Upvotes: 0
Views: 1259
Reputation: 72226
My question is why my
$row2
is false when$row1
is the array as I would've expected?
You expect to get back 3 rows from your query but it only returns 2 rows.
Your query UNION
s three SELECT
s. Each of the last two SELECT
s always return exactly one row. The first SELECT
can return 0 rows or more. Because the table is empty it returns exactly zero rows.
0+1+1
. The query returns exactly 2
rows.
Update:
You expect the rows to be returned in a specific order but the query doesn't require any sorting. SQL works with sets of rows and the sets, as mathematical objects, are unsorted collections (and this is how the SQL handles them).
Without the presence of ORDER BY
in the query, the rows returned by UNION
are not guaranteed to be returned in any order. Not even the order they come from the SELECT
s is not preserved.
If you want to get the rows in the order you wrote the SELECT
queries then you have to add an additional column that tells the order and use in in the ORDER BY
clause:
SELECT `maxcpy`, `stat`, `dtmFrom`, `dtmTo`, 1 AS tableNb
FROM `tblLics`
WHERE `licnm`='zbcdefghijklmnopqrsu'
UNION ALL
SELECT COUNT(*), NULL, NULL, NULL, 2 AS tableNb
FROM `tblUsg`
WHERE `licnm`='zbcdefghijklmnopqrsu'
UNION ALL
SELECT COUNT(*), NULL, NULL, NULL, 3 AS tableNb
FROM `tblUsg`
WHERE `licnm`='zbcdefghijklmnopqrsu'
AND `huid`='a871c47a7f48a12b38a994e48a9659fab5d6376f3dbce37559bcb617efe8662d'
ORDER BY tableNb
This way you know what part of the query generated each of the returned rows.
Remark
You don't need the row returned by the second query. It basically tells you how many rows are returned by the first query but you can also know that by counting the rows having tableNb == 1
in the result set. Since you want the count after the actual rows, it doesn't need an additional traversal of the result set, it can be done while listing the rows from the first query.
Upvotes: 1