I'm trying to export a mysql query table to an excel file. I have it working on another page on my site however it seems to be having trouble with this particular query.
I'm getting this error:
Warning: PDO::query() [pdo.query]: SQLSTATE[42S22]: Column not found: 1054
Unknown column 'u2.confirmed_cash' in 'field list' in
/home2/jtdsdevc/public_html /rbk/usage-v3/inc/excel-exporter
/MySqlExcelBuilder.class.php on line 130
This is my code.
// Setup the SQL Statements
$sql_statement = getReport($idLeague, $idTeam);
function getReport($idLeague, $idTeam){
global $connect;
$sql = "
SELECT idPlayer AS id,
(SELECT CONCAT_WS(' ', location, name) FROM `team` WHERE `team`.id = u.idTeam) AS team,
(SELECT CONCAT_WS(' ', first_name, last_name) FROM `player` WHERE `player`.id = u.idPlayer) AS name,
(SELECT u2.confirmed_cash FROM `usage` u2 WHERE u.idPlayer = u2.idPlayer ORDER BY date DESC LIMIT 1) AS total_cash,
(SELECT u2.confirmed_product FROM `usage` u2 WHERE u.idPlayer = u2.idPlayer ORDER BY date DESC LIMIT 1) AS total_product,
max(date) AS last_entry
FROM `usage` u INNER JOIN `team` t ON u.idTeam =t.id INNER JOIN `league` l ON t.idLeague =l.id WHERE (t.idleague =".$idLeague." or l.pID =".$idLeague." )
";
return $sql;
}
// Add the SQL statements to the spread sheet
$mysql_xls->add_page('Report',$sql_statement);
// Get the spreadsheet after the SQL statements are built...
$phpExcel = $mysql_xls->getExcel(); // This needs to come after all the pages have been added.
....
That's where the error happens. The exact line in the MySqlExcelBuilder.class.php file is:
if ($sh = $this->pdo->query($sql))
The $sql variable above comes out to be
SELECT idPlayer AS id,
(SELECT CONCAT_WS(' ', location, name) FROM `team` WHERE `team`.id = u.idTeam) AS team,
(SELECT CONCAT_WS(' ', first_name, last_name) FROM `player` WHERE `player`.id = u.idPlayer) AS name,
(SELECT u2.confirmed_cash FROM `usage` u2 WHERE u.idPlayer = u2.idPlayer ORDER BY date DESC LIMIT 1) AS total_cash,
(SELECT u3.confirmed_product FROM `usage` u3 WHERE u.idPlayer = u3.idPlayer ORDER BY date DESC LIMIT 1) AS total_product,
max(date) AS last_entry
FROM `usage` u
INNER JOIN `team` t ON u.idTeam =t.id
INNER JOIN `league` l ON t.idLeague =l.id
WHERE (t.idleague =1 or l.pID =1 )
Edit: It is also worth noting that the query by itself works fine in phpMyAdmin.
Problem Solved! I was calling the wrong database, rookie mistake.
Related
I need to add a users full name to the buddy press extended profile field every time a new user is created. This is normal functionality, but we are syncing users from Active Directory and when that ran users names are not being populated. I have created a SQL query that works for combining first and last name and updating it to where i need. My issue comes when trying to create a trigger in phpMyAdmin.
This is the error i receive:
The following query has failed:
CREATE TRIGGER `update users`
AFTER UPDATE ON `wp_bp_xprofile_data`
FOR EACH ROW
CREATE TEMPORARY TABLE user_data AS
SELECT u.user_id
, (SELECT meta_value FROM wp_usermeta WHERE user_id = u.user_id AND meta_key = 'first_name' LIMIT 1) AS first_name
, (SELECT meta_value FROM wp_usermeta WHERE user_id = u.user_id AND meta_key = 'last_name' LIMIT 1) AS last_name
, (SELECT `value` FROM wp_bp_xprofile_data WHERE user_id = u.user_id AND field_id = '1' LIMIT 1) AS bp_name
, (SELECT CONCAT(first_name, ' ', last_name)) AS full_name
FROM wp_bp_xprofile_data u ;
UPDATE wp_bp_xprofile_data u JOIN user_data b ON u.user_id=b.user_id
SET u.value=b.full_name;"
MySQL said: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UPDATE wp_bp_xprofile_data u JOIN user_data b ON u.user_id=b.user_id ' at line 12
Here is the code i used.
CREATE TEMPORARY TABLE user_data AS
SELECT
u.user_id,
(SELECT meta_value FROM wp_usermeta WHERE user_id = u.user_id AND meta_key = 'first_name' LIMIT 1) AS first_name,
(SELECT meta_value FROM wp_usermeta WHERE user_id = u.user_id AND meta_key = 'last_name' LIMIT 1) AS last_name,
(SELECT `value` FROM wp_bp_xprofile_data WHERE user_id = u.user_id AND field_id = '1' LIMIT 1) AS bp_name,
(SELECT CONCAT(first_name, ' ', last_name)) AS full_name
FROM
wp_bp_xprofile_data u
;
UPDATE wp_bp_xprofile_data u
JOIN user_data b
ON u.user_id=b.user_id
SET u.value=b.full_name;
Trigger Inputs
You haven't entered a BRGIN or ENd
Try
DELIMITER //
CREATE TRIGGER `update users`
AFTER UPDATE ON `wp_bp_xprofile_data`
FOR EACH ROW
BEGIN
CREATE TEMPORARY TABLE user_data AS
SELECT u.user_id
, (SELECT meta_value FROM wp_usermeta WHERE user_id = u.user_id AND meta_key = 'first_name' LIMIT 1) AS first_name
, (SELECT meta_value FROM wp_usermeta WHERE user_id = u.user_id AND meta_key = 'last_name' LIMIT 1) AS last_name
, (SELECT `value` FROM wp_bp_xprofile_data WHERE user_id = u.user_id AND field_id = '1' LIMIT 1) AS bp_name
, (SELECT CONCAT(first_name, ' ', last_name)) AS full_name
FROM wp_bp_xprofile_data u ;
UPDATE wp_bp_xprofile_data u JOIN user_data b ON u.user_id=b.user_id
SET u.value=b.full_name;
END //
DELIMITER ;
But i am not sure that trigger will even work, it only removes the syntax errors.
As far as i know, you can't update the table that invoked the Trigger, because your update would also invoke a new trigger and so on.
I'm getting this error :
Query Error : You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ';WITH convs AS ( select c.id, c.title, c.seen, c.id_receiver, c.id_send' at line 1
when i use this query :
$query = ";WITH convs AS (
select c.id, c.title, c.seen, c.id_receiver, c.id_sender
from conversations c
)
select id, title, seen, id_receiver, id_sender
from convs
where id_receiver = '5'
order by title desc limit 0,25";
$res = mysqli_query($connection ,$query);
Am i missing something ?
Your help would be much appreciated.
PS : i minimised the query to make it simple for this context, if you help me find the solution, i may have another problem with the full query. So i might come back to you for more help. Thank's in advance.
EDIT (WHOLE QUERY)
$query = "WITH convs AS (
select c.id, c.title, c.seen, c.id_receiver, c.id_sender,
(select max(date) from messages where id_conversation = c.id and id_user <> '$iduser') as last_msg,
(select top 1 id_user from messages where id_conversation = c.id and id_user <> '$iduser' order by date desc) as last_user,
(select count(distinct id_user) from messages where id_conversation = c.id) as nbruser,
(select count(*) from messages where id_conversation = c.id) as nbrmsg,
(select username from users where id = c.id_sender) as sender, (select username from users where id = c.id_receiver) as receiver,
(select count(*) from deleted_conversations where id_user='$iduser' and id_conversation=c.id) as deleted,
from conversations c
)
select id, title, seen, id_receiver, id_sender, receiver, sender, last_msg, last_user, deleted, nbruser, nbrmsg
from convs
where (id_receiver = '$iduser' or (id_sender == '$iduser' and nbruser > 1)) and deleted = 0
order by last_msg desc limit $pageLimit,$REC_PER_PAGE";
What pushed me to use CTE is the need of using aliases in where clause. And as you can see i have many of them.
Can you give me an example of how to use views/temporary tables to achieve my purpose ?
MySQL/MariaDB doesn't support CTEs. Plus, it is entirely unnecessary in this case:
select id, title, seen, id_receiver, id_sender
from conversations c
where id_receiver = '5'
order by ?? desc
limit 0, 25;
Note: You need to specify the column for the order by as well.
For more complex examples, you can use subqueries, views, and/or temporary tables.
CTEs are quite similar to Derived Tables:
select id, title, seen, id_receiver, id_sender, receiver, sender, last_msg, last_user, deleted, nbruser, nbrmsg
FROM
(
select c.id, c.title, c.seen, c.id_receiver, c.id_sender,
(select max(date) from messages where id_conversation = c.id and id_user <> '$iduser') as last_msg,
(select top 1 id_user from messages where id_conversation = c.id and id_user <> '$iduser' order by date desc) as last_user,
(select count(distinct id_user) from messages where id_conversation = c.id) as nbruser,
(select count(*) from messages where id_conversation = c.id) as nbrmsg,
(select username from users where id = c.id_sender) as sender, (select username from users where id = c.id_receiver) as receiver,
(select count(*) from deleted_conversations where id_user='$iduser' and id_conversation=c.id) as deleted,
from conversations c
) as convs
where (id_receiver = '$iduser' or (id_sender == '$iduser' and nbruser > 1)) and deleted = 0
order by last_msg desc limit $pageLimit,$REC_PER_PAGE
i need speed up this query for list latest messages. This query running too long (eg. 10 seconds ...)
SELECT datas.uid,
datas.message,
datas.date,
CONCAT(conv.first_name, ' ', conv.last_name) AS conversation_name
FROM (SELECT m.message_id,
m.message,
IF (m.from_uid = 1, m.to_uid, m.from_uid) AS uid,
m.readed,
m.sended AS `date`
FROM users u
LEFT JOIN messages m
ON m.from_uid = u.user_id
WHERE m.message_id IN (SELECT MAX(message_id)
FROM messages
WHERE to_uid = 1
OR from_uid = 1
GROUP BY LEAST(from_uid, to_uid),
GREATEST(from_uid, to_uid))) datas
LEFT JOIN users conv
ON conv.user_id = datas.uid
ORDER BY datas.date DESC
LIMIT 5
This query use 2 tables (users and messages).
Table users:
user_id (primary, autoincrement)
login
pass
first_name
last_name
....
Table messages:
message_id (primary, autoincrement)
from_uid (sender message, reference to table users -> user_id)
to_uid (receiver message, reference to table users -> user_id)
sended (timestamp)
message (varchar)
EDIT
I added indexes to messages:
- from_uid
- to_uid
- sended
and this is without efect...
Try creating indexed on the id's you're checking.
In this case you might want to create an index on: conv.user_id, datas.uid, m.message_id, messages.to_uid, messages.from_uid, and datas.date might be a good idea as well, since you're sorting on that.
Add indexes on from_uid and to_uid to speed up the SELECT MAX(message_id) subquery. Otherwise, it has to do a full scan of the table.
I would try and remove the sub query(s)
You can clean it up a bit by joining against users twice when getting the user details from te from and to uid. This way the joins can use indexes effectively. Then just use IF in the SELECT to decide which one to return:-
SELECT IF (m.from_uid = 1, m.to_uid, m.from_uid) AS uid,
m.message,
m.sended AS `date`,
IF (m.from_uid = 1, CONCAT(to_conv.first_name, ' ', to_conv.last_name), CONCAT(from_conv.first_name, ' ', from_conv.last_name)) AS conversation_name
FROM users u
LEFT JOIN messages m
ON m.from_uid = u.user_id
LEFT JOIN users to_conv
ON to_conv.user_id = m.to_uid
LEFT JOIN users from_conv
ON from_conv.user_id = m.from_uid
WHERE m.message_id IN
(
SELECT MAX(message_id)
FROM messages
WHERE to_uid = 1
OR from_uid = 1
GROUP BY LEAST(from_uid, to_uid),
GREATEST(from_uid, to_uid)
)
ORDER BY date DESC
LIMIT 5
The sub query to check the message id is a bit more difficult to remove. Generally IN performs badly. Might be worth changing it to use EXISTS (although this will require the check in the HAVING clause which might not be good)
SELECT IF (m.from_uid = 1, m.to_uid, m.from_uid) AS uid,
m.message,
m.sended AS `date`,
IF (m.from_uid = 1, CONCAT(to_conv.first_name, ' ', to_conv.last_name), CONCAT(from_conv.first_name, ' ', from_conv.last_name)) AS conversation_name
FROM users u
LEFT JOIN messages m
ON m.from_uid = u.user_id
LEFT JOIN users to_conv
ON to_conv.user_id = m.to_uid
LEFT JOIN users from_conv
ON from_conv.user_id = m.from_uid
WHERE EXISTS
(
SELECT MAX(message_id) AS max_message_id
FROM messages
WHERE to_uid = 1
OR from_uid = 1
GROUP BY LEAST(from_uid, to_uid), GREATEST(from_uid, to_uid)
HAVING m.message_id = max_message_id
)
ORDER BY date DESC
LIMIT 5
I'm using php pdo with SQL Server Native Client 11.0 as the driver.
Obiously I do cannot use LIMIT clause as it is proprietary and in trying to workarounf selecting ranges of rows I keep hitting issues.
My setup as follows :
$statement = "SELECT ROW_NUMBER() OVER (ORDER BY USERS.name DESC) AS RowNum, CASE.no, CASE.type, CASE.date, CASE.ju, USERS.name, TBRLMF.rd_rl_description FROM dbo.CASE INNER JOIN dbo.USERS ON dbo.CASE.no = dbo.USERS.case_no INNER JOIN dbo.CMSTBRLMF ON dbo.USERS.relationship = dbo.TBRLMF.code ";
if($exact == 'checked'){
$exact = '=';
}else{
$exact = 'LIKE';
}
if($searchtype == 'users'){
$statement .= " WHERE USERS.name $exact '%$searchstring%'";
}else{
$statement .= " WHERE USERS.no $exac '%$searchstring%'";
}
$statement .= " AND RowNum BETWEEN :offset AND :max";
$statement = $dbh->prepare($statement);
$statement->bindParam(':offset', $offset, PDO::PARAM_INT);
$statement->bindParam(':max', $max, PDO::PARAM_INT);
and as long as I do not include the line of code :
$statement .= " AND RowNum BETWEEN :offset AND :max";
It works fine but gives me all the data.
When that line is included I recieve the following error :-
caught exception 'PDOException' with message 'SQLSTATE[42S22]: Column not found: 207 [Microsoft][SQL Server Native Client 11.0][SQL Server]Invalid column name 'RowNum'. (SQLExecute[207] at ext\pdo_odbc\odbc_stmt.c:254)' in C:\pub\test\Classes\Core.php:44
I am at a loss and MSSQL is new to me.
Help much appreciated.
The predicate on that column can't be in a WHERE clause. (The predicates in the WHERE clause are evaluated when the rows are accessed; the value of that expression (analytic function) isn't available until after the rows are accessed.
You may be able to reference the column alias in a HAVING clause:
" HAVING RowNum BETWEEN ... ";
You can't use COLUMN ALIAS (RowNum in your case) in WHERE clause. Rather change your query using derived table like below
SELECT * FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY USERS.name DESC) AS RowNum,
CASE.no,
CASE.type,
CASE.date,
CASE.ju,
USERS.name,
TBRLMF.rd_rl_description
FROM dbo.CASE
INNER JOIN dbo.USERS
ON dbo.CASE.no = dbo.USERS.case_no
INNER JOIN dbo.CMSTBRLMF
ON dbo.USERS.relationship = dbo.TBRLMF.code
WHERE USERS.name LIKE '%string%'
AND USERS.no LIKE '%string%'
) X
WHERE RowNum BETWEEN 1 AND 10;
EDIT:
You can also use CTE (Common Table Expression) to get around this like below
Create the CTE
WITH NEWCTE AS
(
SELECT ROW_NUMBER() OVER (ORDER BY USERS.name DESC) AS RowNum,
CASE.no,
CASE.type,
CASE.date,
CASE.ju,
USERS.name,
TBRLMF.rd_rl_description
FROM dbo.CASE
INNER JOIN dbo.USERS
ON dbo.CASE.no = dbo.USERS.case_no
INNER JOIN dbo.CMSTBRLMF
ON dbo.USERS.relationship = dbo.TBRLMF.code
WHERE USERS.name LIKE '%searchstring%'
AND USERS.no LIKE '%searchstring%'
)
Query the CTE
SELECT *
FROM NEWCTE
WHERE RowNum BETWEEN 1 AND 10
I am struggling with a MYSQL query - I have 2 tables :
Table 1 (info) containing UID, first_name, last_name.
Table 2 (card) containing UID, pic .
What I am trying to do is get all results into an array:
WHERE UID IN '$ids' AND LEFT(last_name,1) = '$letter' ORDER BY last_name, first_name ASC
I figured an INNER JOIN so my current code is:
("SELECT UID, first_name, last_name, pic FROM
(SELECT info.first_name,info.last_name,card.pic FROM info
INNER JOIN card ON info.UID=card.UID)
WHERE LEFT(last_name,1) = '$letter' ORDER BY last_name, first_name ASC")
This is producing the following error though:
'Every derived table must have it's own alias'.
Am I going about this the right way with inner join, and how do I give the derived table an alias? Thanks in advance!
select b.UID, g.first_name, g.last_name, b.pic
from user_data.general_info g
inner join user_data.Bcards b on g.UID = b.UID
where LEFT(g.last_name, 1) = '$letter'
order by g.last_name, g.first_name asc
The inner query should be named.
SELECT users.UID, users.first_name, users.last_name, users.pic FROM
(SELECT info.first_name,info.last_name,card.pic FROM user_data.general_info
INNER JOIN user_data.Bcards ON general_info.UID=Bcards.UID) users
WHERE LEFT(users.last_name,1) = '$letter' ORDER BY users.last_name, users.first_name ASC