I have a query on a table with some encrypted fields like so:
SELECT groups.`group_id` AS id, `description_s`,
AES_DECRYPT(`description_l`, 'decryption_key') AS `description`,
AES_DECRYPT(groups.`email`, 'decryption_key') AS email,
...
FROM groups
WHERE ...
GROUP BY `id`, `description_s`,`description`,`email`,...
ORDER BY id DESC
This works as expected, giving me the decrypted output. However if I add a join to another table.
SELECT groups.`group_id` AS id, `description_s`,
AES_DECRYPT(`description_l`, 'decryption_key') AS `description`,
...
FROM groups
INNER JOIN details on details.`group_id` = groups.`group_id`
WHERE ...
GROUP BY `id`, `description_s`,`description`,`email`,`customer_name`
ORDER BY id DESC
The result columns are no longer decrypted and the grouping only works if I put the AES_DECRYPT(description_l,dec_key) rather than the alias description in the 'group by' clause. Still leaving me with encrypted columns.
I found a workaround by using subqueries, and doing the decryption on the outside.
SELECT id,description_s, AES_DECRYPT(`description_l`, 'decryption_key') as description
FROM (
SELECT groups.`group_id` as id, `description_s`, `description_l`
FROM groups
INNER JOIN details ON details.`group_id`=groups.`group_id`
WHERE ...
GROUP BY `id`, `description_s`,description_l
) subq
ORDER BY id DESC
I am curious to know what exactly is going on. Why does the column not get decrypted at all in the second example above? Is there a way to get the grouped,decrypted result without using subqueries?
Related
I have this query:
SELECT
DISTINCT (entries.guid),
locales.*,
locales.guid as locale_guid,
entries.*,
node.category_guid,
node.title as node_title,
nodelocs.caption as node_caption,
nodelocs.uri as node_uri,
nodelocs.url as node_url
FROM entries AS entries
JOIN entry_locales AS locales ON (locales.entry_guid=entries.guid)
LEFT JOIN nodes AS node ON (node.guid=entries.node_guid)
LEFT JOIN node_locales AS nodelocs ON (nodelocs.node_guid=entries.node_guid AND nodelocs.lang_guid=locales.lang_guid)
LEFT JOIN metrics as metrics_default ON (entries.guid = metrics_default.entry_guid)
WHERE
metrics_default.customer_guid='453b894967968204'
AND metrics_default.metrics='entryview'
AND locales.lang_guid='4b5747548a5bd457'
AND locales.state='1' AND entries.node_guid IN (SELECT child_guid FROM node_children WHERE guid IN ('4b084f280caffbef') ) ORDER BY metrics_default._updated DESC LIMIT 0,10
So I want to get items with unique guids and want to order it by '_updated' field from 'metricts_default' table. But nothing happens.
If I delete DISTINCT() - result is fine, but with duplicates.
you misunderstand the distinct
keyword distinct here does not mean you will get distinct entries.guid, but different row
what this mean is the row with same guid but different In other fields will not be eliminated by MySQL.
This query is in the ColdFusion, and it can be run for the old version ColdFusion, but can't run this query right now. Just reminds me Column "TUser.LastName" is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
<CFQUERY name="getUserList" datasource="#REQUEST.dsn#" maxrows="1">
SELECT
TUser.userID as user_ID,
Min(TUser.agencyID) as agencyID,
Min(TUser.servicing_EntityID) as servicing_EntityID,
Min(Tuser.userid) AS userID,
Min(Tuser.lastname) AS lastName,
Min(Tuser.firstname) AS firstName,
Min(Tuser.isSecondary) AS isSecondary,
Min(Tuser.corporate_ID) AS corporate_ID,
Min(Tuser.city) AS city,
Min(TUser.address1) AS address1,
Min(Corporate_Client.client_name) AS client_name,
Min(TLocationProvState.abrev) AS abrev,
TUser_Loyalty.loyalty_ID AS loyalty_ID
FROM TUser
LEFT JOIN TLocationProvState ON (Tuser.provinceID = TLocationProvState.PROVSTATEID)
LEFT JOIN Corporate_Client ON (Tuser.corporate_ID = Corporate_Client.client_ID)
LEFT JOIN TUser_Loyalty ON (Tuser.userid = TUser_Loyalty.userID)
LEFT JOIN TLoyalty ON (TUser_Loyalty.loyalty_ID = TLoyalty.loyalty_ID)
WHERE (0=1)
GROUP BY TUser.UserID, TUser_Loyalty.loyalty_ID
ORDER BY TUser.LastName, TUser.FirstName, TUser.User_ID
</CFQUERY>
Your order by is invalid, Use the alias of the columns instead of the min name's
WHERE (0=1)
GROUP BY TUser.UserID, TUser_Loyalty.loyalty_ID
ORDER BY LastName, FirstName, User_ID
Also odd...
in order by you have Tuser.user_ID but select shows TUser.userID (no underscore)
order of operation in the SQL has the order by generated after the select, thus column aliases are available.
You are attempting to ORDER by fields that have not been designated as group fields. The fields will have to be returned in order to order by, therefore, the Query Executor needs to know how to handle all fields in a grouped statement.
GROUP BY TUser.UserID, TUser_Loyalty.loyalty_ID, TUser.LastName, TUser.FirstName
ORDER BY TUser.User_ID, TUser.LastName, TUser.FirstName
OR
GROUP BY TUser.UserID, TUser_Loyalty.loyalty_ID
ORDER BY TUser.User_ID, MIN(TUser.LastName), MIN(TUser.FirstName)
I have two tables in MySql db.
1) networks (NetworkId, NetworkType)
2) users (Id, NetworkId, IpAddress)
Using [NetworkId and IpAddress] defines unique users.
Now, I want to use group by clause on NetworkType and at the same time want to list count of all users as like below:
SELECT (SELECT Count(distinct IpAddress) FROM users
WHERE NetworkId in nr.NetworkId ) as UsersCount
FROM networks as nr
GROUP BY NetworkType;
But due to any reason I always gets zero users.
When I run following queries
SELECT GROUP_CONCATE(nr.NetworkId)
FROM networks as nr
GROUP BY NetworkType;
Then I am getting valid values with ',' separated.
Thanks in advance.
Updated per your new information about what you needed with the group by.
How about an upvote for my efforts at least.
Latest SQLFIDDLE
select
mysub.count,
nr.`networkid`
from
`networks` as nr,
(select
count(`ipaddress`) as count,
`networkid`
from
`users`
where
`networkid`
in (
select
`networkid`
from
`networks`
)
group by
`networkid`) as mysub
where nr.`networkid` = mysub.`networkid`
group by nr.`networkid`
Something like this perhaps:
select n.networktype, count(distinct u.ipaddress)
from networks n
join users u on n.networkid = u.networkid
group by n.networktype
This is puzzling me and no amount of the Google is helping me, hoping someone can point me in the right direction.
Please note that I have omitted some fields from the tables that don't relate to the question just to simplify things.
contacts
contact_id
name
email
contact_uuids
uuid
contact_id
visitor_activity
uuid
event
contact_communications
comm_id
contact_id
employee_id
Query
SELECT
`c`.*,
(SELECT COUNT(`log_id`) FROM `contact_communications` `cc` WHERE `cc`.`contact_id` = `c`.`contact_id`) as `num_comms`,
(SELECT MAX(`date`) FROM `contact_communications` `cc` WHERE `cc`.`contact_id` = `c`.`contact_id`) as `latest_date`,
(SELECT MIN(`date`) FROM `contact_communications` `cc` WHERE `cc`.`contact_id` = `c`.`contact_id`) as `first_date`,
(SELECT COUNT(`vaid`) FROM `visitor_activity` `va` WHERE `va`.`uuid` = `cu`.`uuid`) as `num_act`
FROM `contacts` `c`
LEFT JOIN `contact_uuids` `cu` ON `c`.`contact_id` = `cu`.`contact_id`
GROUP BY `c`.`contact_id`
ORDER BY `c`.`name` ASC
Some contacts have multiple UUIDs (upwards of 20 or 30).
When I perform the query WITHOUT the GROUP BY statement, I get the results I expect - a row returned for each UUID that exists for that contact, with the correct "num_comms" and "num_act" numbers.
However when I add the GROUP BY statement, the "num_comms" is a lot smaller then expected and the "num_act" returns only the value from the first row without the GROUP BY statement.
I tried doing a "WHERE NOT IN" in the subquery, however that simply crashed the server as it was far too intense.
So - how do I get this to add up all the COUNT values from the LEFT JOIN and not just return the first value?
Also if anyone can help me optimize this that would be great.
Two problems:
GROUP BY c.contact_id does not include all the non-aggregate columns. This is a MySQL extension. What you get is random values for the rows other than contact_id
The JOIN adds confusion. Your only use for visitor_activity is the COUNT(*) one it. But that does not make sense since it is limited to one UUID, whereas the row is limited to one contact_id. Rethink the purpose of that.
Remove this line:
(SELECT COUNT(`vaid`) FROM `visitor_activity` `va` WHERE `va`.`uuid` = `cu`.`uuid`) as `num_act`
and the rest may work ok.
I will continue with the assumption that you want the COUNT of all rows in visitor_activity for all the uuids associated with the one contact_id.
See if this:
( SELECT COUNT(*)
FROM `contacts` c2
JOIN `visitor_activity` USING(uuid)
WHERE c2.contact_id = c.contact_id as `num_act` ) AS num_act
will work for the last subquery. At the same time, remove the JOIN:
LEFT JOIN `contact_uuids` `cu` ON `c`.`contact_id` = `cu`.`contact_id`
Now, back to the other problem (the non-standard usage of GROUP BY). Assuming that contact_id is the PRIMARY KEY, then simply remove the
GROUP BY `c`.`contact_id`
I have couple tables joined in MySQL - one has many others.
And try to select items from one, ordered by min values from another table.
Without grouping in seems to be like this:
Code:
select `catalog_products`.id
, `catalog_products`.alias
, `tmpKits`.`minPrice`
from `catalog_products`
left join `product_kits` on `product_kits`.`product_id` = `catalog_products`.`id`
left join (
SELECT MIN(new_price) AS minPrice, id FROM product_kits GROUP BY id
) AS tmpKits on `tmpKits`.`id` = `product_kits`.`id`
where `category_id` in ('62')
order by product_kits.new_price ASC
Result:
But when I add group by, I get this:
Code:
select `catalog_products`.id
, `catalog_products`.alias
, `tmpKits`.`minPrice`
from `catalog_products`
left join `product_kits` on `product_kits`.`product_id` = `catalog_products`.`id`
left join (
SELECT MIN(new_price) AS minPrice, id FROM product_kits GROUP BY id
) AS tmpKits on `tmpKits`.`id` = `product_kits`.`id`
where `category_id` in ('62')
group by `catalog_products`.`id`
order by product_kits.new_price ASC
Result:
And this is incorrect sorting!
Somehow when I group this results, I get id 280 before 281!
But I need to get:
281|1600.00
280|2340.00
So, grouping breaks existing ordering!
For one, when you apply the GROUP BY to only one column, there is no guarantee that the values in the other columns will be consistently correct. Unfortunately, MySQL allows this type of SELECT/GROUPing to happen other products don't. Two, the syntax of using an ORDER BY in a subquery while allowed in MySQL is not allowed in other database products including SQL Server. You should use a solution that will return the proper result each time it is executed.
So the query will be:
For one, when you apply the GROUP BY to only one column, there is no guarantee that the values in the other columns will be consistently correct. Unfortunately, MySQL allows this type of SELECT/GROUPing to happen other products don't. Two, the syntax of using an ORDER BY in a subquery while allowed in MySQL is not allowed in other database products including SQL Server. You should use a solution that will return the proper result each time it is executed.
So the query will be:
select CP.`id`, CP.`alias`, TK.`minPrice`
from catalog_products CP
left join `product_kits` PK on PK.`product_id` = CP.`id`
left join (
SELECT MIN(`new_price`) AS "minPrice", `id` FROM product_kits GROUP BY `id`
) AS TK on TK.`id` = PK.`id`
where CP.`category_id` IN ('62')
order by PK.`new_price` ASC
group by CP.`id`
The thing is that group by does not recognize order by in MySQL.
Actually, what I was doing is really bad practice.
In this case you should use distinct and by catalog_products.*
In my opinion, group by is really useful when you need group result of agregated functions.
Otherwise you should not use it to get unique values.