I have wrote a SQL query which I am using in my model, provided below:
Tag.find_by_sql(["SELECT tags.id, tags.name, count(*) AS count FROM tags
INNER JOIN taggings ON tags.id = taggings.tag_id
WHERE
(taggings.taggable_type = 'Discussion' AND taggings.taggable_id IN (SELECT id FROM `discussions` WHERE discussions.group_id = ?))
GROUP BY tag_id ORDER BY ? LIMIT ?;", self.id, self.id, self.id, self.id, order, limit])
This works fine and pulls out the required tags. However the tags do not order correctly. I noticed in the server console that the query has apostrophes around the order statement like so:
ORDER BY 'count desc'
When I remove the apostrophes, like so:
ORDER BY count desc
and run the query manually it pulls the tags in the correct order. Is there a way to stop the apostrophes being added to the query?
Cheers
Tony
the reason is because you have parameterized the column name
ORDER BY ?
The value you have pass has been sanitized that's why it becomes 'count desc'.
You cannot pass column names and tables name by design. The only way is to concatenate the column name within the string.
Related
I'm trying to retrieve the data set by locating a string based on its occurrence, check the below query -
select name, LOCATE('test', name)
from afkapi_dev.articles
where name like '%test%'
order by LOCATE('test', name) ASC
The result set is -
Result set is perfectly fine, but the issue here is the ordering.
Can anyone explain why "testing" is listed above "test low" and also suggest a way to make this happen.
Thank you
You seem to be asking to do further sorting on name. For multiple level sorting, you can specify different columns/expressions in ORDER BY clause, separated by comma, with respective sorting order [ASC or DESC]
Also, you can alias the LOCATE(..) expression in the SELECT clause, and reuse that in the ORDER BY. This should prevent re-computation of LOCATE(..) values.
select name, LOCATE('test', name) AS location
from afkapi_dev.articles
where name like '%test%'
order by location ASC, name ASC
I am learning SQL now and I am kind of confused when encountering a query like this:
SELECT CASE
WHEN url like '%abc.com%'THEN 'abc'
When url like '%def.com%'THEN 'def'
When url like '%smiley.com%' THEN 'Smiley'
Else 'others'
End AS 'sites', count(*)
FROM websites_sources
GROUP BY 1;
The query above works correctly, but only if the GROUP BY Statement uses 1. If I write Group BY 'sites', the result only shows 'others' and the total count of ALL rows (instead of the count for 'others' only and other sites).
My question is, so for GROUP BY Statement we can only use number to indicate grouping, and not the name of the column?
Thanks for your help!
Only use single quote for string and date constants. Never use single quotes for column aliases. You'll just confuse yourself.
Try this:
SELECT (CASE WHEN url like '%abc.com%' THEN 'abc'
WHEN url like '%def.com%' THEN 'def'
WHEN url like '%smiley.com%' THEN 'Smiley'
ELSE 'others'
END) AS sites,
count(*)
FROM websites_sources
GROUP BY sites;
You are grouping by the string 'sites', which is a constant, not the column named sites.
We are fetching list of ordered products from database including join with order table.
We want to list all orders with how many quantity of products order in each order on the basis of passed product ids. We also want to display customer name which was placed the order. So, as per our knowledge we have created an query to get items as:
SELECT
`main_table`.*,
`order`.*,
SUM(main_table.qty_ordered - main_table.qty_canceled) AS `custom_qty`,
SUM(main_table.row_total) AS `custom_row_total`,
SUM(main_table.tax_amount) AS `tax_amount`,
SUM(main_table.hidden_tax_amount) AS `hidden_tax_amount`,
SUM(main_table.discount_amount) AS `discount_amount`,
CONCAT(order.customer_firstname, ' ' ,order.customer_middlename, ' ', order.customer_lastname) AS full_name
FROM `sales_flat_order_item` AS `main_table`
INNER JOIN `sales_flat_order` AS `order` ON main_table.order_id=order.entity_id
WHERE (((((main_table.product_id = '902') OR (main_table.product_id = '903') OR (main_table.product_id = '904'))))) AND (main_table.store_id = '1') AND (CONCAT(order.customer_firstname, order.customer_middlename, order.customer_lastname) like '%rag%')
GROUP BY `main_table`.`sku`
All the aggregate functions used in above query working fine except concat(). Every time we will get the value of full_name column as NULL even we have name the corresponding concatenated columns.
Please any one helps me to figure out why this is not working. Are we doing something wrong in the above query?
Thanks in advance.
As CONCAT() returns NULL if any argument is NULL I'm guessing maybe one of the three arguments is NULL?
Try using the CONCAT_WS() function instead (as you use separators anyway) which skips null values.
CONCAT_WS(' ', order.customer_firstname, order.customer_middlename, order.customer_lastname) AS full_name
See the documentation for more information.
On a side note: you might want to look into how you can use table aliases to shorten the query text and make it more readable.
Are you sure EVERY column has an value? (Middlename?)
The MYSQL manual says:
SELECT CONCAT('My', NULL, 'QL')
-> NULL
I have data TSA, TSB, TSC, Total.
How to display this alphabetically with Total always the last one.
Currently I have this and of course it doesn't work.
select * from table where main_id =x group by col-name asc
Certainly I can't use desc because I have another record ABC, BCA, CDA, Total.
So how to add "except if col-name is Total"? or perhaps there is another way?
Kind of hard to be sure with your post (not a lot of detail in there). But you could probably use a case statement to evaluate your column, and sort on that. Something like
case when <your column> = 'Total' then 'ZZZ' else <your column> end as SortKey
Then you can just order by that new column.
User order by field:
select * from table
where main_id =x
order by FIELD( `col-name`, 'Total' ), t;
See:
SQL Fiddle Example
Refer to:
MySQL: FIELD(str,str1,str2,str3,...)
Return the index (position) of the first argument in the subsequent
arguments.
What is wrong with this:
SELECT *,
GROUP_CONCAT(DISTINCT w.tag_word ORDER BY w.tag_word ASC SEPARATOR ' ') AS tags,
MATCH (title, description, tags) AGAINST ('london') AS score
FROM article G
JOIN tag_index I ON G.article_id = I.tag_target_id
JOIN tag_word W ON I.tag_word_id = W.tag_word_id
WHERE I.tag_type_id = 1 AND MATCH (title, description, tags) AGAINST ('london')
GROUP BY G.article_id
I get the error 'Unknown column 'tags' in 'field list''
UPDATE:
Thank you Parrots for pointing out that I need the HAVING clause. I still can not figure out how to implement it. I can only guess it can not be done in one query and needs to be a subquery.
Since "tags" a value you're creating using GROUP_CONCAT you need to use the having clause. Whenever you want to apply a condition to stuff after the grouping, use having. It works the same as where just after the grouping.
Where in your code example is trying to be applied to filter the results from article that will eventually be grouped to build things like "tags".