mysql - php blob field? - php

I have a query that returns as a result what seems to be a BLOB
SELECT CAST(GROUP_CONCAT(CONCAT(value,'(',qty,')') SEPARATOR ', ') AS CHAR)a
FROM (
SELECT value,count(*) qty
FROM extra_field_values
WHERE fieldid = #fieldid
AND value != ''
AND itemid IN (7,8,10,12,15,16,17,18,19,20,21,22,23,24,25,26)
GROUP BY value
) x
the table is
CREATE TABLE `extra_field_values` (
`itemid` int(11) NOT NULL DEFAULT '0',
`fieldid` int(11) NOT NULL DEFAULT '0',
`value` text NOT NULL,
KEY `itemid` (`itemid`),
KEY `fieldid` (`fieldid`),
KEY `value` (`value`(1)),
KEY `inx` (`itemid`,`fieldid`,`value`(1))
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
The main idea is that i want a string per row returning value:::count separated by ###.
The problem is that php returns empty result. I have tried both mysql and mysqli as far as drivers is concerned.
Any ideas?
PHP
$result = $mysqli->query(" SELECT CAST(GROUP_CONCAT(CONCAT(value,'(',qty,')') SEPARATOR ', ') AS CHAR)a
FROM (
SELECT value,count(*) qty
FROM extra_field_values
WHERE fieldid = #fieldid
AND value != ''
AND itemid IN (7,8,10,12,15,16,17,18,19,20,21,22,23,24,25,26)
GROUP BY value
) x ") ;
while( $row = $result->fetch_assoc() ){
print_r($row);
}
Even if you execute it through phpmyadmin it returns null. Try it on EMS mysql it works like a charm.
full query
SELECT
extra_field_values.fieldid,
extra_fields.var_name,
extra_fields.field,
extra_fields.type,
#fieldid:=extra_field_values.fieldid,
(
SELECT CAST(GROUP_CONCAT(CONCAT(value,'(',qty,')') SEPARATOR ', ') AS CHAR) a
FROM ( SELECT value, #fieldid, count(*) qty FROM extra_field_values WHERE fieldid = #fieldid GROUP BY value ) x
) as v,
count(itemid) as total,
(SELECT groupid FROM extra_fields_groups_items WHERE itemid = #fieldid) as groupid
FROM extra_field_values INNER JOIN extra_fields
ON (extra_field_values.fieldid=extra_fields.fieldid)
WHERE module = 'listings'
AND itemid IN (7,8,10,12,15,16,17,18,19,20,21,22,23,24,25,26)
AND settings LIKE '%"search";s:1:"1"%'
GROUP BY fieldid

You are querying for fields matching the session variable #fieldid but I would guess you're not defining that variable in your mysqli session or in your phpmyadmin environment.
SET #fieldid := 1234;
SELECT ... WHERE fieldid = #fieldid ...
Or else you can use ? as a query parameter placeholder for the fieldid and bind it to a PHP variable.
See http://php.net/manual/en/mysqli-stmt.bind-param.php
Does the following query do what you want, without using the #fieldid session variable?
SELECT x.fieldid, x.var_name, x.field, x.type, x.groupid, COUNT(*) AS total,
CAST(GROUP_CONCAT(CONCAT(x.value,'(',x.qty,')') SEPARATOR ', ') AS CHAR) a
FROM (
SELECT v.value, v.fieldid, f.var_name, f.field, f.type, g.groupid, COUNT(*) AS qty
FROM extra_field_values AS v
INNER JOIN extra_fields AS f ON f.fieldid=v.fieldid
INNER JOIN extra_fields_groups_item AS g ON g.itemid=v.fieldid
WHERE f.module = 'listings'
AND f.itemid IN (7,8,10,12,15,16,17,18,19,20,21,22,23,24,25,26)
AND f.settings LIKE '%"search";s:1:"1"%'
GROUP BY v.value, v.fieldid
) as x
GROUP BY x.fieldid

Related

How to add non-empty values from two tables in mySQL DB using php?

I have two tables inside a mysql database. table_1 and table_2
Both of these tables have 4 columns for users
user_1, user_2, user_3 and user_4
Now using PHP I first want to fetch the non-null values from two tables and I use this query.
<?php
$query1 = "
select * from table_1 where user_1!='' and user_1 is not null
union all
select * from table_1 where user_2!='' and user_2 is not null
union all
select * from table_1 where user_3!='' and user_3 is not null
union all
select * from table_1 where user_4!='' and user_4 is not null
";
Then I fetch it and count the entries total = mysqli_num_rows and it gives me correct details as 3.
Similarly I do it for table_2
<?php
$query2 = "
select * from table_2 where user_1!='' and user_1 is not null
union all
select * from table_2 where user_2!='' and user_2 is not null
union all
select * from table_2 where user_3!='' and user_3 is not null
union all
select * from table_2 where user_4!='' and user_4 is not null
";
and it shows me total count as 2 which is correct.
But when I add count1 and count2
$count1 = mysqli_num_rows($data1);
$count2 = mysqli_num_rows($data2);
$total = $count1+$count2;
It shows either 1 or some weird value.Please suggest a fix
Everything depends on what $data1 and $data2 is. If they contain the results of $query and $query2, respectively, then one could expect the result to be 5. However, since your result is different, it follows that $data1 and $data2 is not what you think. So, in order to find out what the problem is, you will need to find out what $data1 and $data2 is. You will need to var_dump them and analyze what their value is, detect the nature of the anomaly. Once that's done, you will need to look at the code and figure out how that value was ending up into your variables.
to getting which column is not empty, you should add some condition as AND and if your fields have whitespace please consider TRIM condition such as:
SELECT * FROM `table_1` WHERE `user_1` IS NOT NULL AND TRIM(column) <> '' union all
notice: if you want use more than one command in php variable as string, you should add semicolon on end of each command
$query ="
SELECT * FROM `table_1` WHERE `user_1` IS NOT NULL AND TRIM(user_1) <> '' union all;
SELECT * FROM `table_2` WHERE `user_2` IS NOT NULL AND TRIM(user_2) <> '' union all;
SELECT * FROM `table_3` WHERE `user_3` IS NOT NULL AND TRIM(user_3) <> '' union all;
"

Subquery in INSERT executed differently in PDO than SQL

I want to insert a new dataset into a MySQL table tab with external data, but also with data from another table otherTab using the others' table primary key and another condition. However, it could be that the requested row simply does not exist (anymore) or the result set is empty due to a mismatch in the other supplied data. Then, the original INSERT should fail. All columns are forbidden to be NULL.
My first attempt was:
INSERT INTO tab (id, extid1, extid2, value)
SELECT 1,
(SELECT id FROM otherTab WHERE id = 12 AND data = 'TXT'),
(SELECT id FROM otherTab WHERE id = 34 AND data = 'JPG'),
1234
but the problem with it is that a returned empty result set is cast to the type of the column in tab, leading to a 0 as entry data.
The query shall be efficient and avoid unnecessary querying. This is how I achieve it with four subqueries:
INSERT INTO tab (id, extid1, extid2, value)
SELECT 1,
(SELECT id FROM otherTab WHERE id = 12 AND data = 'TXT'),
(SELECT id FROM otherTab WHERE id = 34 AND data = 'JPG'),
1234
WHERE EXISTS (SELECT id FROM otherTab WHERE id = 12 AND data = 'TXT')
AND EXISTS (SELECT id FROM otherTab WHERE id = 34 AND data = 'JPG')
I tried with other constructs, e.g. (SELECT IFNULL(SELECT id FROM otherTab WHERE id = 12 AND data = 'TXT', NULL)) to enforce NULL or even a string into the target column, but it also gets casted to a 0 or some value instead.
Here is the code for dbFiddle:
code
CREATE TABLE `tab` (
`id` int NOT NULL,
`seUuid4` binary(16) NOT NULL,
`rxUuid4` binary(16) NOT NULL,
`text` varchar(16)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
CREATE TABLE `otherTab` (
`uuid4` binary(16) NOT NULL,
`lgUuid4` binary(16) NOT NULL,
`data` varchar(16)
) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
ALTER TABLE `otherTab`
ADD PRIMARY KEY(`uuid4`);
ALTER TABLE `tab`
ADD CONSTRAINT `tab_ibfk_1` FOREIGN KEY (`rxUuid4`) REFERENCES `otherTab` (`uuid4`) ON DELETE RESTRICT ON UPDATE RESTRICT,
ADD CONSTRAINT `tab_ibfk_2` FOREIGN KEY (`seUuid4`) REFERENCES `otherTab` (`uuid4`) ON DELETE RESTRICT ON UPDATE RESTRICT;
INSERT INTO `otherTab` (uuid4, lgUuid4, data) VALUES
(UNHEX("22224444aaaa49c782408b2fe8c4dee0"), UNHEX("00001234aaaa4444aaaa432187654321"), "JPG"),
(UNHEX("11113333aaaa49c782408b2fe8c4dee0"), UNHEX("12340000bbbb6666bbbb432187654321"), "TXT");
INSERT INTO tab (id, seUuid4, rxUuid4, text)
SELECT
1,
(SELECT uuid4 FROM otherTab WHERE lgUuid4 = UNHEX('00001234aaaa4444aaaa432187654321') AND data = 'JPK' LIMIT 0,1),
(SELECT uuid4 FROM otherTab WHERE lgUuid4 = UNHEX('12340000bbbb6666bbbb432187654321') AND data = 'TXT' LIMIT 0,1),
'some text'
This interestingly works exactly as expected: Note the JPK instead of JPG. I verified my code and the PDO prepared statement fires out exactly the same command, but it gets inserted as INSERT INTO tab (id, seUuid4, rxUuid4) VALUES (1, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 'datatext'); while the SQL client and phpMyadmin deliver the expected cannot insert null error message.
I could not find anything in the PDO options. If it helps, I use PDO with emulated prepared statements, but also tried without with no change.
PS: I posted already at dba.stackexchange.com/posts/276868
You could use a subquery:
INSERT INTO tab (id, extid1, extid2, value)
SELECT
FROM (
SELECT
1 id,
(SELECT id FROM otherTab WHERE id = 12 AND data = 'TXT') extid1,
(SELECT id FROM otherTab WHERE id = 34 AND data = 'JPG') extid2
1234 value
) t
WHERE extid1 IS NOT NULL and extid2 IS NOT NULL
Or, probably better yet, you can CROSS JOIN the two subqueries:
INSERT INTO tab (id, extid1, extid2, value)
SELECT 1, t1.id, t2.id, 1234
FROM (SELECT id FROM otherTab WHERE id = 12 AND data = 'TXT') t1,
CROSS JOIN (SELECT id FROM otherTab WHERE id = 34 AND data = 'JPG') t2
Actually, since you are reurning the same value that you are filtering on, two exists subqueries are probably sufficient:
INSERT INTO tab (id, extid1, extid2, value)
SELECT t.*
FROM (SELECT 1 id, 12 extid1, 34 extid2, 1234 value) t
WHERE EXISTS (SELECT 1 FROM otherTab t1 WHERE t1.id = t.extid1 AND t1.data = 'TXT')
AND EXISTS (SELECT 1 FROM otherTab t1 WHERE t1.id = t.extid2 AND t1.data = 'JPG')

Mysql limit results based on value from column

I'm trying to limit the number of results of a query based on another table column. For example, I have a table for products and a config table, like this:
tb_product
id | active | name | value | ...
tb_config
max_product | ...
What I'd like to do is something like this
SELECT
a.name, a.value
FROM
tb_product a,
tb_config b
WHERE a.active = 1
LIMIT b.max_product
But I'm getting errors like #1327 - Undeclared variable: b. Is there a way to achieve this result?
Because currently what I'm doing is doing another query to get just the max_product value and then use it as php variable to limit the results, like this:
$limit = "SELECT max_product FROM tb_config";
SELECT name, value FROM tb_product WHERE ativo = 1 LIMIT $limit
Maybe....
SELECT a.name
, a.value
FROM tb_product a
CROSS JOIN (SELECT #Limit:=(SELECT max_product from tb_config))
WHERE a.active = 1
LIMIT #Limit
With help from #ENargit's answer in Variable LIMIT Clause in MySQL, you can do it using a row count variable.
Assuming the following schema:
CREATE TABLE
tb_product
(
id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(10),
`value` VARCHAR(10)
);
INSERT INTO
`tb_product`
(`name`, `value`)
VALUES
('Name1','Value1'),
('Name2','Value2'),
('Name3','Value3'),
('Name4','Value4'),
('Name5','Value5'),
('Name6','Value6'),
('Name7','Value7'),
('Name8','Value8'),
('Name9','Value9'),
('Name10','Value10');
CREATE TABLE
`tbl_config`
(
id INT PRIMARY KEY AUTO_INCREMENT,
`type` VARCHAR(10),
`value` INT
);
INSERT INTO
`tbl_config`
(`type`,`value`)
VALUES
('something',10),
('maxrows',7);
You can reference the config table with a subquery:
SELECT * FROM (
SELECT
tb_product.*,
#rownum := #rownum + 1 AS RowNum
FROM tb_product,
(SELECT #rownum := 0) AS CounterTbl
) AS DataTbl
WHERE
RowNum <= (
SELECT
`value`
FROM
`tbl_config`
WHERE
`type` = 'maxrows'
);
Gives you the first 7 rows (according to the config value). You can obviously extend this to do sorting etc.
SQLFiddle: http://www.sqlfiddle.com/#!9/f789e4/2

Finding last "Non-Null" value in a Pivot query

I have the following query:
SELECT * FROM
(
SELECT unix_timestamp, input_raw, tag_id
from [200030].[dbo].inputs
WHERE inputs.date_time > dateadd(day,-1,getdate())
AND
(tag_id = 92164 or tag_id = 92149)
) src
pivot
(
max(input_raw)
FOR tag_id IN ([92164], [92149])
) piv
ORDER by unix_timestamp DESC
which is great and works. It gives me the results:
However, I would like the query to do one more thing for me.
Whenever there is a 'NULL' result, I would like the query to replace the 'NULL' with the last 'non-NULL' value in the column.
For example, the first NULL seen in column '92164' would be replaced with '211'.
Also, it is possible that there will be several 'NULL's i a row, so the query would need to keep going up the column until it finds a none NULL.
I have been able to accomplish this with php. Putting the results into a 2D associative array and running a function that finds nulls then loops through to find the last non NULL, but I really want to do this all in SQL if possible. I'd much rather use the
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC)){
//code
}
method than assigning several arrays.
Any help?
Thank you
//EDIT
Forgot to add that this only applies if there is any non-nulls above the null value. For example it is acceptable if the first row is NULL.
You can put your pivot query in a CTE and reuse the CTE when you figure out what value to show. You data have null values only in the first column but here is a version that deals with the nulls in both columns.
WITH C AS
(
SELECT *
FROM (
SELECT unix_timestamp, input_raw, tag_id
FROM inputs
WHERE date_time > dateadd(day,-1,getdate()) AND
(tag_id = 92164 OR tag_id = 92149)
) src
PIVOT
(
MAX(input_raw)
FOR tag_id IN ([92164], [92149])
) piv
)
SELECT C1.unix_timestamp,
(
SELECT TOP(1) C2.[92164]
FROM C AS C2
WHERE C1.unix_timestamp <= C2.unix_timestamp AND
C2.[92164] IS NOT NULL
ORDER BY C2.unix_timestamp
) AS [92164],
(
SELECT TOP(1) C2.[92149]
FROM C AS C2
WHERE C1.unix_timestamp <= C2.unix_timestamp AND
C2.[92149] IS NOT NULL
ORDER BY C2.unix_timestamp
) AS [92149]
FROM C AS C1
ORDER by C1.unix_timestamp DESC;
If you have a performance problem it might be faster for you to store the result from the CTE in a temp table with a useful clustered key index.
CREATE TABLE #C
(
unix_timestamp int PRIMARY KEY,
[92164] int,
[92149] int
);
INSERT INTO #C
SELECT *
FROM (
SELECT unix_timestamp, input_raw, tag_id
FROM inputs
WHERE date_time > dateadd(day,-1,getdate()) AND
(tag_id = 92164 OR tag_id = 92149)
) src
PIVOT
(
MAX(input_raw)
FOR tag_id IN ([92164], [92149])
) piv;
SELECT C1.unix_timestamp,
(
SELECT TOP(1) C2.[92164]
FROM #C AS C2
WHERE C1.unix_timestamp <= C2.unix_timestamp AND
C2.[92164] IS NOT NULL
ORDER BY C2.unix_timestamp
) AS [92164],
(
SELECT TOP(1) C2.[92149]
FROM #C AS C2
WHERE C1.unix_timestamp <= C2.unix_timestamp AND
C2.[92149] IS NOT NULL
ORDER BY C2.unix_timestamp
) AS [92149]
FROM #C AS C1
ORDER by C1.unix_timestamp DESC;
DROP TABLE #C;
You can use an adaptation of the "running total" calculation method detailed here. Create a temp table or table variable to hold the results of your pivot query, with an extra column to hold the last not-null value of the 92164 column. I can't get SQLFiddle to do this, but it works on my machine (famous last words)
CREATE TABLE #pivot_results ([unix_timestamp] int, [92164] int, [92149] int)
INSERT INTO #pivot_results ([unix_timestamp], [92164], [92149])
VALUES
(1361893407, NULL, 294),
(1361893218, 207, 294),
(1361893108, NULL, 292),
(1361892807, 211, 292),
(1361892799, NULL, 292)
CREATE TABLE #update_me
([unix_timestamp] int, [92164] int, [92149] int, last_not_null_92164 int)
DECLARE #last_not_null_92164 INT = NULL;
INSERT INTO #update_me([unix_timestamp], [92164], [92149], last_not_null_92164)
SELECT unix_timestamp, [92164], [92149], NULL
FROM #pivot_results
ORDER BY unix_timestamp DESC
UPDATE #update_me
SET #last_not_null_92164 = last_not_null_92164 = ISNULL([92164],#last_not_null_92164)
FROM #update_me
SELECT
unix_timestamp
,last_not_null_92164 AS [92164]
,[92149]
FROM #update_me
ORDER BY unix_timestamp DESC

SQL most popular

I have a mysql table with items in relation to their order.
CREATE DATABASE IF NOT EXISTS `sqltest`;
USE `sqltest`;
DROP TABLE IF EXISTS `testdata`;
CREATE TABLE `testdata` (
`orderID` varchar(10) DEFAULT NULL,
`itemID` varchar(10) DEFAULT NULL,
`qtyOrdered` int(10) DEFAULT NULL,
`sellingPrice` decimal(10,2) DEFAULT NULL
)
INSERT INTO `testdata`(`orderID`,`itemID`,`qtyOrdered`,`sellingPrice`)
values ('1','a',1,'7.00'),('1','b',2,'8.00'),('1','c',3,'3.00'),('2','a',1,'7.00'),('2','c',4,'3.00');
Intended Result:
A = (1+1)2
B = 2
C = (2+4)6 <- most popular
How do I add up all the qty's for each item and result the highest one?
It should be fairly strait forward but I'm new to SQL and I can't work this one out :S
Solution needs to be mysql and or php.
I guess there needs to be some sort of temporary tally variable for each item ID,
but that seems like it could get messy with too many items.
ANSWER:
(thanks nuqqsa)
SELECT itemID, SUM(qtyOrdered) AS total FROM testdata GROUP BY itemID ORDER BY total DESC LIMIT 1;
How about this:
SELECT itemID, SUM(qtyOrdered) AS total FROM testdata GROUP BY itemID ORDER BY total DESC;
SELECT itemID, SUM(qtyOrdered) as blah FROM sqltest GROUP BY itemID ORDER BY blah DESC should do it
SELECT *
FROM testdata
ORDER BY SUM(gtyOrdered) DESC
GROUP BY itemID
SELECT SUM( qtyOrdered ) AS sum_ordered, itemID
FROM testdata
GROUP BY itemID
ORDER BY sum_ordered
select count(qtyOrdered), qtyOrdered from testdata group by qtyOrdered

Categories