SQL JOIN having a result of table rows to columns - mysql

I'm trying to connect two tables and show the matching rows as columns.
ps_product table contains the values of the product, ps_image_shop contains the image values and id's linking to the product. What I would like to have is, showing matching rows as column at SQL result below.
Table 1 (ps_product) 1
Table 2 (ps_image_shop) 2
CURRENT SQL QUERY
SELECT SQL_CALC_FOUND_ROWS p.`id_product` AS `id_product`,
p.`reference` AS `reference`,
sa.`price` AS `price`,
p.`id_shop_default` AS `id_shop_default`,
p.`is_virtual` AS `is_virtual`,
pl.`name` AS `name`,
pl.`link_rewrite` AS `link_rewrite`,
sa.`active` AS `active`,
shop.`name` AS `shopname`,
image_shop.`id_image` AS `id_image`,
cl.`name` AS `name_category`,
0 AS `price_final`,
pd.`nb_downloadable` AS `nb_downloadable`,
sav.`quantity` AS `sav_quantity`,
IF(sav.`quantity`<=0, 1, 0) AS `badge_danger`
FROM `ps_product` p
LEFT JOIN `ps_product_lang` pl ON (pl.`id_product` = p.`id_product` AND pl.`id_lang` = 1 AND pl.`id_shop` = 1)
LEFT JOIN `ps_stock_available` sav ON (sav.`id_product` = p.`id_product` AND sav.`id_product_attribute` = 0 AND sav.id_shop = 1 AND sav.id_shop_group = 0 )
JOIN `ps_product_shop` sa ON (p.`id_product` = sa.`id_product` AND sa.id_shop = 1)
LEFT JOIN `ps_category_lang` cl ON (sa.`id_category_default` = cl.`id_category` AND cl.`id_lang` = 1 AND cl.id_shop = 1)
LEFT JOIN `ps_category` c ON (c.`id_category` = cl.`id_category`)
LEFT JOIN `ps_shop` shop ON (shop.id_shop = 1)
LEFT JOIN `ps_image_shop` image_shop ON (image_shop.`id_product` = p.`id_product` AND image_shop.id_shop = 1)
LEFT JOIN `ps_image` i ON (i.`id_image` = image_shop.`id_image`)
LEFT JOIN `ps_product_download` pd ON (pd.`id_product` = p.`id_product`)
WHERE (1 AND state = 1)
ORDER BY `id_product` desc
LIMIT 0, 100;
CREATE QUERIES
CREATE TABLE IF NOT EXISTS `ps_product` (
`id_product` int(10) unsigned NOT NULL,
`id_supplier` int(10) unsigned DEFAULT NULL,
`id_manufacturer` int(10) unsigned DEFAULT NULL,
`id_category_default` int(10) unsigned DEFAULT NULL,
`id_shop_default` int(10) unsigned NOT NULL DEFAULT '1',
`id_tax_rules_group` int(11) unsigned NOT NULL,
`on_sale` tinyint(1) unsigned NOT NULL DEFAULT '0',
`online_only` tinyint(1) unsigned NOT NULL DEFAULT '0',
`ean13` varchar(13) DEFAULT NULL,
`isbn` varchar(32) DEFAULT NULL,
`upc` varchar(12) DEFAULT NULL,
`ecotax` decimal(17,6) NOT NULL DEFAULT '0.000000',
`quantity` int(10) NOT NULL DEFAULT '0',
) ENGINE=InnoDB AUTO_INCREMENT=138 DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `ps_image_shop` (
`id_product` int(10) unsigned NOT NULL,
`id_image` int(11) unsigned NOT NULL,
`id_shop` int(11) unsigned NOT NULL,
`cover` tinyint(1) unsigned DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Related

SQL error near 'GROUP BY u.id ORDER BY u.user ASC LIMIT 0,100' at line 1

I need to grab all the groups a user is in and put them together as one string in order to be abble to search by terms using like statement. I am not sure whats the problem with my query ... no matter how long I look at it, I don't see what the problem is...
#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 'GROUP BY u.id ORDER BY u.user ASC LIMIT 0,100' at line 1
SELECT
u.id,
u.user AS USER,
CONCAT(u.prenom, ' ', u.nom) AS nom,
GROUP_CONCAT(g.titre SEPARATOR ', ') AS gtitre,
e.nom AS etablissement,
u.bloque,
u.date_invitation,
u.completed
FROM
_USER u
LEFT JOIN ETABLISSEMENT_USER AS eu
ON
eu.id_user = u.id
LEFT JOIN ETABLISSEMENT AS e
ON
e.id = eu.id_etablissement
LEFT JOIN ETABLISSEMENT_USER AS eu2
ON
eu2.id_user = u.id
LEFT JOIN ETABLISSEMENT AS e2
ON
e2.id = eu2.id_etablissement
LEFT JOIN _USER_GROUPS AS ug
ON
ug.user_id = u.id
LEFT JOIN _GROUPS AS g
ON
g.id = ug.group_id
WHERE
(
(
SELECT
MIN(g.ordre)
FROM
`_GROUPS` g
JOIN `_USER_GROUPS` UG ON
g.id = UG.group_id
WHERE
UG.user_id = u.id
) >= 1 OR(
SELECT
MIN(UG.group_id)
FROM
`_USER_GROUPS` UG
WHERE
UG.user_id = u.id
) IS NULL
) AND(u.innactif = 0)
HAVING
gtitre LIKE '%coord%'
GROUP BY
u.id
ORDER BY
u.user ASC
LIMIT 0, 100
If I remove the HAVING gtitre LIKE '%coord%' from the above it all works fine ...
How can I filter my users based on if there group contains or not the searched string?
This is my table structure for the users, the hroups and the pivot table
CREATE TABLE `_GROUPS` (
`id` int(11) UNSIGNED NOT NULL,
`titre` text NOT NULL,
`ordre` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='contient les rôles et les tâches';
CREATE TABLE `_USER` (
`id` int(10) UNSIGNED NOT NULL,
`innactif` int(11) NOT NULL DEFAULT '0',
`pwd` varchar(255) NOT NULL DEFAULT '',
`user` varchar(100) NOT NULL DEFAULT '',
`courriel` varchar(150) NOT NULL,
`prenom` varchar(255) NOT NULL,
`nom` varchar(100) NOT NULL DEFAULT '',
`mdp_recup` varchar(255) DEFAULT NULL,
`essai` int(3) NOT NULL,
`bloque` datetime DEFAULT NULL,
`expiration` datetime DEFAULT NULL,
`facteur` smallint(5) DEFAULT NULL,
`authentificator` varchar(255) DEFAULT NULL,
`sexe` varchar(255) NOT NULL,
`telephone` varchar(255) NOT NULL,
`dashboard` varchar(255) DEFAULT NULL,
`titre` varchar(255) DEFAULT NULL,
`creation` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`expiration_compte` datetime DEFAULT NULL,
`contact_principal` tinyint(1) DEFAULT NULL,
`id_langue` int(10) UNSIGNED DEFAULT NULL,
`ext` varchar(10) DEFAULT NULL,
`invitation` text,
`date_invitation` datetime DEFAULT NULL,
`completed` tinyint(1) DEFAULT NULL,
`afficher_site` tinyint(1) DEFAULT NULL,
`id_programme` text,
`id_programme_c` text,
`ordre` int(9) NOT NULL,
`courriel_promo` int(9) NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `_USER_GROUPS` (
`user_id` int(11) UNSIGNED DEFAULT NULL,
`group_id` int(11) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
You have to use HAVING after GROUP BY

WHERE in a triple INNER JOIN

I'm trying to find all the values where empresas.id = (a number);
Here's my query:
SELECT empresas.nome, departamentos.nomeDepartamento,
funcionarios.nomeFuncionario, funcionarios.email, funcionarios.idFuncionario FROM empresas
INNER JOIN departamentos ON empresas.id = departamentos.idEmpresas
INNER JOIN funcionarios ON departamentos.id = funcionarios.idDepartamentos
ORDER BY empresas.nome ASC;
I've tried to put WHERE in the end, right after ASC :
...ORDER BY empresas.nome ASC WHERE id.empresas = 2;
And none of my tries have worked.
Tables:
CREATE TABLE `departamentos` (
`id` int(11) NOT NULL,
`idEmpresas` int(11) DEFAULT NULL,
`nomeDepartamento` varchar(30) DEFAULT NULL
)
CREATE TABLE `empresas` (
`id` int(11) NOT NULL,
`nome` varchar(30) DEFAULT NULL
)
CREATE TABLE `funcionarios` (
`idFuncionarios` int(11) NOT NULL,
`idDepartamentos` int(11) DEFAULT NULL,
`nomeFuncionario` varchar(30) DEFAULT NULL,
`email` varchar(30) DEFAULT NULL,
`senha` varchar(30) DEFAULT NULL
)
What i wanna do is JOIN those table to return empresas.nome, departamentos.nomeDepartamento,
funcionarios.nomeFuncionario, funcionarios.email, funcionarios.idFuncionario and then select then by empresas.
Thank you for your help!
SELECT empresas.nome, departamentos.nomeDepartamento,
funcionarios.nomeFuncionario, funcionarios.email, funcionarios.idFuncionario FROM empresas
INNER JOIN departamentos ON empresas.id = departamentos.idEmpresas
INNER JOIN funcionarios ON departamentos.id = funcionarios.idDepartamentos
WHERE empreas.id = 2 /* <=== The line to add */
ORDER BY empresas.nome ASC;

OR operator slowing down MySQL query

I have four tables each relating to the others by some fields: games, teams, altnames, countries.
Wrote this query with an OR operator in an ON clause (see line 6) which slows down the query very much:
select ROUND(AVG(attendance)), competition, team1, countries.* from games
LEFT JOIN (teams
INNER JOIN countries ON ( countries.iso3 = teams.country )
LEFT JOIN altnames ON ( altnames.entityType = "team" AND altnames.season = "1011" AND altnames.entityId = teams.longName )
)
ON ( altnames.altValue = games.team1 OR teams.longName = games.team1 )
where games.season="1011" group by games.competition, games.team1 having AVG(attendance)>= 500 order by AVG(attendance) desc
Query is fast enough when not using the OR, only one of the two conditions at a time:
1.
select ROUND(AVG(attendance)), competition, team1, countries.* from games
LEFT JOIN (teams
INNER JOIN countries ON ( countries.iso3 = teams.country )
LEFT JOIN altnames ON ( altnames.entityType = "team" AND altnames.season = "1011" AND altnames.entityId = teams.longName )
)
ON ( altnames.altValue = games.team1 )
where games.season="1011" group by games.competition, games.team1 having AVG(attendance)>= 500 order by AVG(attendance) desc
2.
select ROUND(AVG(attendance)), competition, team1, countries.* from games
LEFT JOIN (teams
INNER JOIN countries ON ( countries.iso3 = teams.country )
LEFT JOIN altnames ON ( altnames.entityType = "team" AND altnames.season = "1011" AND altnames.entityId = teams.longName )
)
ON ( teams.longName = games.team1 )
where games.season="1011" group by games.competition, games.team1 having AVG(attendance)>= 500 order by AVG(attendance) desc
Any idea why is this happening, and how the first query can be speed up?
EDIT:
Here are the tables:
altnames:
CREATE TABLE IF NOT EXISTS `altnames` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`entityType` enum('team','comp','logo') NOT NULL,
`entityId` varchar(50) NOT NULL DEFAULT '0',
`season` varchar(4) NOT NULL DEFAULT '0',
`altValue` varchar(50) NOT NULL DEFAULT '0',
KEY `id` (`id`),
KEY `entityType_season_altValue` (`entityType`,`season`,`altValue`)
)
countries:
CREATE TABLE IF NOT EXISTS `countries` (
`name` varchar(50) NOT NULL,
`iso2` varchar(2) NOT NULL,
`iso3` varchar(3) NOT NULL,
`color` varchar(7) NOT NULL,
KEY `iso3` (`iso3`)
)
games:
CREATE TABLE IF NOT EXISTS `games` (
`id` int(7) NOT NULL AUTO_INCREMENT,
`competition` varchar(10) NOT NULL,
`season` varchar(4) NOT NULL,
`stage` varchar(10) DEFAULT NULL,
`gamedate` date DEFAULT NULL,
`team1` varchar(50) NOT NULL,
`team2` varchar(50) NOT NULL,
`score1` tinyint(2) DEFAULT NULL,
`score2` tinyint(2) DEFAULT NULL,
`attendance` int(11) DEFAULT NULL,
`location` varchar(100) DEFAULT NULL,
`source` varchar(400) DEFAULT NULL,
`altsource` varchar(400) DEFAULT NULL,
`note` varchar(400) DEFAULT NULL,
KEY `id` (`id`),
KEY `competition_season` (`competition`,`season`),
KEY `team_comp_season` (`team1`,`competition`,`season`)
)
teams:
CREATE TABLE IF NOT EXISTS `teams` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`shortName` varchar(20) DEFAULT NULL,
`longName` varchar(50) NOT NULL,
`urlSlug` varchar(50) DEFAULT NULL,
`country` varchar(3) NOT NULL DEFAULT 'NSP',
`competitions` varchar(50) DEFAULT NULL,
`latitude` float(10,6) DEFAULT '0.000000',
`longitude` float(10,6) DEFAULT '0.000000',
`inactive` tinyint(1) DEFAULT '0',
KEY `id` (`id`),
KEY `long` (`longName`),
KEY `FK_teams_countries` (`country`),
CONSTRAINT `teams_ibfk_1` FOREIGN KEY (`country`) REFERENCES `countries` (`iso3`)
)
I just had a funny idea in mind While waiting for an expert opinion,
Try to switch OR operator with AND.
conditionA OR conditionB
is equivalent to
NOT(NOT(conditionA) and NOT(conditionB))
Good Luck,

trouble creating update query using 3 tables mysql

I Have closing balances in Akey table and i have pool id in cpp table i want to update value of Bppd key_amount column with akey closing_balance but before
that i have to check the default_pool='ACTIVE' from table cpp
sample tables are mentioned
TABLE Akey (
`id` int(11) NOT NULL,
`serial_key` varchar(82) DEFAULT NULL,
`closing_balance` double(20,2) DEFAULT '0.00',
`product_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)
TABLE Bppd(
`id` int(11) NOT NULL AUTO_INCREMENT,
`pool_id` int(11) DEFAULT NULL,
`product_id` int(11) DEFAULT NULL,
`akey_id` int(11) DEFAULT NULL,
`key_amount` double DEFAULT '0',
`working_balance` double DEFAULT '0',
PRIMARY KEY (`id`)
)
TABLE Cpp (
`id` int(11) NOT NULL AUTO_INCREMENT,
`akey_id` int(11) DEFAULT NULL,
`pool_id` int(11) DEFAULT NULL,
`default_pool` varchar(15) DEFAULT NULL,
PRIMARY KEY (`id`)
)
I have Following query
UPDATE `Bppd` ppd
JOIN AKey kk ON ppd.`akey_id` = kk.`id`
JOIN `Cpp` pp ON pp.`akey_id` = kk.`id` AND pp.`default_pool` = 'ACTIVE' AND ppd.`akey_id` = pp.`akey_id`
SET ppd.`key_amount`= kk.`closing_balance`
Try this
UPDATE Bppd b INNER JOIN Akey a on a.id = b.akey_id AND a.product_id = b.product_id
INNER JOIN Cpp c ON b.key_id = c.akey_id AND b.pool_id = c.pool_id
SET b.key_amount = a.closing_balance
WHERE c.default_pool='ACTIVE'
Or this:
UPDATE Bppd b SET key_amount = (SELECT closing_balance FROM Akey a WHERE a.id = b.akey_id and a.product_id = b.product_id)
WHERE EXISTS (
SELECT 1 FROM Cpp c
WHERE b.akey_id = c.akey_id AND b.pool_id = c.pool_id
AND c.default_pool='ACTIVE'
)
AND EXISTS (
SELECT 1 FROM Akey a
WHERE a.id = b.akey_id and a.product_id = b.product_id
)

sql can't figure out the query

I have three tables:
CREATE TABLE IF NOT EXISTS `contacts` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`providerId` int(10) unsigned NOT NULL DEFAULT '0',
`requestId` int(10) unsigned NOT NULL DEFAULT '0',
`status` binary(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
CREATE TABLE IF NOT EXISTS `messages` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`fromuid` int(255) NOT NULL,
`touid` int(255) NOT NULL,
`sentdt` datetime NOT NULL,
`read` tinyint(1) NOT NULL DEFAULT '0',
`readdt` datetime DEFAULT NULL,
`messagetext` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
)
CREATE TABLE IF NOT EXISTS `users` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`email` varchar(255) DEFAULT NULL,
`mobile` varchar(15) NOT NULL,
`password` varchar(255) NOT NULL,
`city` varchar(255) NOT NULL,
`zip` varchar(15) DEFAULT NULL,
`device` varchar(50) DEFAULT NULL,
`version` varchar(10) DEFAULT NULL,
`photo` varchar(255) DEFAULT NULL,
`created` datetime NOT NULL,
`live` enum('0','1') NOT NULL DEFAULT '1',
`authenticationTime` datetime NOT NULL,
`userKey` varchar(255) DEFAULT NULL,
`IP` varchar(50) DEFAULT NULL,
`port` int(10) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `firstname` (`mobile`,`city`,`zip`)
)
And this SQL query that finds out friends/contacts for specified user (user id 1 in this case):
SELECT u.id
,u.mobile
,u.name
,(NOW() - u.authenticationTime) AS authenticateTimeDifference
,u.IP
,f.providerid
,f.requestid
,f.status
,u.port
FROM contacts f
LEFT JOIN users u ON u.id =
IF (
f.providerid = 1
,f.requestid
,f.providerid
) WHERE (
f.providerid = 1
AND f.status = 1
)
OR f.requestid = 1
That works fine but I want to be able to also join messages table and show user's friends/contacts who have talked latest (meaning latest conversations first) with order by messages.sentdt desc option but I am unable to figure out how to do that, I tried all joins but none worked :(
Your help will be greatly appreciated. Thanks
Update
Here is sample data above query returns:
In that same resultset, I want to be able to sort based on order by messages.sentdt desc but I am not sure how to pull that in and sort resultset by latest message first
Try this:
select u.id
, u.mobile
, u.name
, (NOW() - u.authenticationTime) as authenticateTimeDifference
, u.IP
, f.providerid
, f.requestid
, f.status
, u.port
from contacts f
left join users u
on u.id = if (f.providerid = 1, f.requestid, f.providerid)
left join (select fromuid, max(sentdt) as sentdt from messages group by fromuid) m
on m.fromuid = if (f.providerid = 1, f.providerid, f.requestid)
where (f.providerid = 1 and f.status = 1)
or f.requestid = 1
order by m.sentdt