I had a query which was working just fine:
#schedule = Schedule.find(params[:id])
#schedule_tasks = ScheduleTask.select("s.*, t.*, t.*, d.*, st.*").from("schedule_tasks st").
joins("left join schedules s ON s.id = st.schedule_id").
joins("left join tasks t ON t.id = st.task_id").
joins("right join days d ON d.id = st.day_id").
order("d.number, t.name").
group_by{|d| d.number}
I had to refine my search to only schedule_tasks with a specific schedule_id, so I edited the second line to:
joins("left join schedules s ON s.id = st.schedule_id AND s.id = ?", #schedule.id).
This has cause the following error:
unknown class: Fixnum
The error goes away if I take out the group_by - but I need that, and I have tried hard coding in the number instead of #schedule.id and that does not work either, a google search does not reveal a lot of details on this error.
For anyone coming here from Google, I used plain string interpolation to fix this issue. This method is vulnerable to SQL Injection, so make sure you type check your variables before using them.
In this case I would do
#schedule_id = #schedule.id
.
.
.
joins("left join schedules s ON s.id = st.schedule_id AND s.id = #{#schedule_id}")
Rather than following learning_to_swim's answer, which as noted is at risk of SQL injection, couldn't you cast your #schedule_id to a string?
#tasks = ScheduleTask.joins("left join [...] s.id = ?", #schedule.id.to_s)
Related
I'm trying to update records through a single inner join with multiple criteria. My best effort so far is this:
UPDATE FormData d
INNER JOIN ProductGrowthDays g
ON d.ProductCode = g.ProductCode AND
ON d.ProductionLineCode = g.ProductionLineCode AND
ON g.MonthIndex = MONTH(d.SowingDate)
SET d.EstimatedDays = g.GrowingDays
WHERE
d.EventTypeId = 1
Access gives the error 'Syntax error (missing operator)' and highlights the 'r' in 'd.ProductCode'. The join is guaranteed to give a single row.
Could anyone give me pointers on how to fix this?
D'oh. The answer was as follows:
UPDATE FormData d
INNER JOIN ProductGrowthDays g
ON (d.ProductCode = g.ProductCode
AND d.ProductionLineCode = g.ProductionLineCode
AND g.MonthIndex = MONTH(d.SowingDate))
SET d.EstimatedDays = g.GrowingDays
WHERE
d.EventTypeId = 1
I was sure I tried that at one point, but obviously not. Well, leaving this here if someone else should need it.
SELECT
i.*,
ii.file_location
FROM group_shop_item i, group_shop_itemimage ii, group_shop_brand b
WHERE
i.brand_id = b.id
AND
b.brand_status_id = 1
AND
i.is_deleted = 0
AND
i.is_displayed = 1
AND
i.id = ii.item_id
AND
ii.is_main = 1
AND
i.deal_participate = 1
AND
i.brand_label_id IS NOT NULL
ORDER BY i.datetime_modified DESC;
This SQL query keeps throwing me a 1064. It seems to be on the last line which I've tried with and without the i table variable. I can't for the life of me catch the error, anyone can lend me another pair of eyes?
I'm throwing this as a RAW query into the in built Django function and building this query with string concatenation. This copy paste is directly from a print I've done from the command line. It's outputting neatly but isn't reading when I run the view on my browser.
Over 25 years ago ANSI Standard join syntax was adopted. You need to cease using comas between table names in the from clause.
SELECT
i.*
, ii.file_location
FROM group_shop_item i
INNER JOIN group_shop_itemimage ii ON i.id = ii.item_id
INNER JOIN group_shop_brand b ON i.brand_id = b.id
WHERE i.is_deleted = 0
AND i.is_displayed = 1
AND ii.is_main = 1
AND i.deal_participate = 1
AND i.brand_label_id IS NOT NULL
AND b.brand_status_id = 1
;
Regarding the 1064 error, please read this without the exact error message and the exact/full query we can't offer much insight into that.
The other thing you need to be careful of is that "select *" isn't good practice either.
I have two tables, packages (with id, name as attributes) and releases (with url, upload_time, downloaded_bytes as attributes). Every package can have arbitrary many releases. I want a list of all packages with their latest release.
Currently, I have the following working code:
sql = ("SELECT `packages`.`id`, `name` FROM `packages`")
cursor.execute(sql)
packages = cursor.fetchall()
for pkg in packages:
sql = ("SELECT `url` FROM `releases` "
"WHERE `package_id` = %s "
"AND `downloaded_bytes` = 0 "
"ORDER BY `upload_time` DESC LIMIT 1")
cursor.execute(sql, (pkg['id'], ))
url = cursor.fetchone()
if url is not None:
package_url = url['url']
package_analysis.main(pkg['name'], package_url)
logging.info("Package '%s' done.", pkg['name'])
However, I think this is an ugly solution as I execute a lot of queries where I should only execute one query.
Can I do this in one query? How would the query look like?
Please note: I only want one result for each package. That means, the package numpy should only give the result for url="https://pypi.python.org/packages/cp35/n/numpy/numpy-1.10.1-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl" (version 1.10.1) and not 99 results.
What I've tried
SELECT
`packages`.`id`,
`packages`.`name`,
`releases`.`url`,
`releases`.`upload_time`,
`releases`.`release_number`
FROM
`packages`
JOIN
`releases` ON `releases`.`package_id` = `packages`.`id`
GROUP BY
`packages`.`name`
ORDER BY
`releases`.`upload_time` DESC
But that gives a seemingly random value for upload_time (and also url).
You can try this query:
select p.id, p.name, r.url, r.upload_time, r.release_number from
(select p.id, max(r.release_number) release_number from packages p
join releases r on p.id = r.package_id
group by p.id) a
join packages p on p.id = a.id
join releases r on r.release_number = a.release_number
It assumes that release_number is sortable, if not possible you can use max upload time instead.
Based on this answer (thank you Emiswelt) for mentioning it:
SELECT
`packages`.`id`,
`packages`.`name`,
`o`.`url`,
`o`.`upload_time`,
`o`.`release_number`
FROM
`releases` o
LEFT JOIN
`releases` b ON `o`.`package_id` = `b`.`package_id`
AND `o`.`upload_time` < `b`.`upload_time`
JOIN
`packages` ON `packages`.`id` = o.package_id
WHERE
`b`.`upload_time` is NULL
AND `o`.`downloaded_bytes` = 0
ORDER BY
`packages`.`name`
LIMIT 10
The query finishes execution within a fraction of a second.
I'm attempting to write a query that I know is compatible with MySQL to MS Access. This is a programming assignment, so I'm not expecting an answer straight up given to me, but I don't know MS Access' version of SQL well enough. I wrote the MySQL myself, and tested it to be working. That's when I realized that the query needed to work for MS Access instead. So here is the known code:
SELECT `D`.`RENT_NUM`,
`R`.`RENT_DATE`,
`D`.`VID_NUM`,
`M`.`MOVIE_TITLE`,
`D`.`DETAIL_DUEDATE`,
`D`.`DETAIL_RETURNDATE`,
`D`.`DETAIL_FEE`,
`D`.`DETAIL_RETURNDATE` - `D`.`DETAIL_DUEDATE` AS `DAYS_LATE`
FROM `detailrental` AS `D`
JOIN `rental` AS `R` ON `D`.`RENT_NUM` = `R`.`RENT_NUM`
JOIN `video` AS `V` ON `D`.`VID_NUM` = `V`.`VID_NUM`
JOIN `movie` AS `M` ON `V`.`MOVIE_NUM` = `M`.`MOVIE_NUM`
WHERE `D`.`DETAIL_RETURNDATE` - `D`.`DETAIL_DUEDATE` > 0
ORDER BY `R`.`RENT_NUM`, `M`.`MOVIE_TITLE`;
I've been attempting to convert to MS Access SQL, but I still don't get it. Here is the most recent attempt.
SELECT [D].[RENT_NUM],
[R].[RENT_DATE],
[D].[VID_NUM],
[M].[MOVIE_TITLE],
[D].[DETAIL_DUEDATE],
[D].[DETAIL_RETURNDATE],
[D].[DETAIL_FEE],
[D].[DETAIL_RETURNDATE] - [D].[DETAIL_DUEDATE] AS [DAYS_LATE]
FROM [DETAILRENTAL] AS [D] INNER JOIN
(
[RENTAL] AS [R] INNER JOIN
(
[VIDEO] AS [V] INNER JOIN [MOVIE] AS [M] ON [V].[MOVIE_NUM] = [M].[MOVIE_NUM]
) ON [D].[VID_NUM] = [V].[VID_NUM]
) ON [D].[RENT_NUM] = [R].[RENT_NUM]
WHERE [D].[DETAIL_RETURNDATE] - [D].[DETAIL_DUEDATE] > 0
ORDER BY [R].[RENT_NUM], [M].[MOVIE_TITLE];
The error I receive is Syntax error in JOIN operation. I know what that means, but I don't know MS Access' SQL well enough to spot the error.
It has been a while since I had to write any access query, so I just went with syntax described by official documentation http://msdn.microsoft.com/en-us/library/office/bb208854(v=office.12).aspx. Figured out it had syntax error in it. So to make query work you have to wrap JOIN with parenthesis. But each ON statement still needs to be inside each set of parenthesis not on outside. This should do the trick.
SELECT [D].[RENT_NUM]
,[R].[RENT_DATE]
,[D].[VID_NUM]
,[M].[MOVIE_TITLE]
,[D].[DETAIL_DUEDATE]
,[D].[DETAIL_RETURNDATE]
,[D].[DETAIL_FEE]
,[D].[DETAIL_RETURNDATE] - [D].[DETAIL_DUEDATE] AS [DAYS_LATE]
FROM (
(
(
[detailrental] AS [D] )
INNER JOIN [rental] AS [R]
ON [D].[RENT_NUM] = [R].[RENT_NUM] )
INNER JOIN [video] AS [V]
ON D.VID_NUM = [V].[VID_NUM] )
INNER JOIN [movie] AS [M]
ON [V].[MOVIE_NUM] = [M].[MOVIE_NUM]
WHERE [D].[DETAIL_RETURNDATE] - [D].[DETAIL_DUEDATE] > 0
ORDER BY [R].[RENT_NUM]
,[M].[MOVIE_TITLE];
Since we know that the problem is with the JOINs let's start from the innermost set of parentheses and work outwards:
[VIDEO] AS [V]
INNER JOIN
[MOVIE] AS [M]
ON [V].[MOVIE_NUM] = [M].[MOVIE_NUM]
That looks fine. Let's move out one level:
[RENTAL] AS [R] INNER JOIN
(
[VIDEO] AS [V]
INNER JOIN
[MOVIE] AS [M]
ON [V].[MOVIE_NUM] = [M].[MOVIE_NUM]
)
ON [D].[VID_NUM] = [V].[VID_NUM]
This JOIN won't work. Can you see why?
I'm working within a product collection returning products and trying to order them. The problem is one of my product attributes (I find this out at 90% of the way through my project) is a quantity, i.e. 250, 5000 etc. However, I've just found out that despite these being numbers Magento treats them as strings, so therefore the collection returns the following quantities in this example:
50,100,250,500,1000,2000,5000
However, addAttributeToSort('quantity','ASC'); does this:
100,1000,2000,250,50,500,5000
I've done a var_dump() on the collection and ascertained that the values are being treated as strings, hence why this is probably happening. Unfortunately I've got over 6000 products with a lot of custom implementations and configurable products depending on this attribute, so am reluctant to change it. Searching on here I found that adding ORDER BY 'quantity' *1 does actually perform the sort correctly, however I can't seem to implement this clause in the standard addAttributeToSort function.
If anyone could help me implement this, I've tried addAttributeToSort('quantity','*1'); but that doesn't work, just errors.
Many thanks
UPDATE:
Here's the syntax for the query which is generated from the following code:
$collection = $this->getUsedProductCollection($product)
->addAttributeToSelect('*')
->addFieldToFilter('name', array( 'like' => '%' . $stock . '%' ));
$collection->getSelect()->order(new Zend_Db_Expr('quantity' *1));
count($collection);
'SELECT 'e'.*, 'link_table'.'parent_id', IF(at_name.value_id > 0, at_name.value, at_name_default.value) AS 'name', 'price_index'.'price', 'price_index'.'tax_class_id', 'price_index'.'final_price', IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS 'minimal_price', 'price_index'.'min_price', 'price_index'.'max_price', 'price_index'.'tier_price' FROM 'catalog_product_entity' AS 'e' INNER JOIN 'catalog_product_super_link' AS 'link_table' ON link_table.product_id = e.entity_id INNER JOIN 'catalog_product_website' AS 'product_website' ON product_website.product_id = e.entity_id AND product_website.website_id = '1' INNER JOIN 'catalog_product_entity_varchar' AS 'at_name_default' ON ('at_name_default'.'entity_id' = 'e'.'entity_id') AND ('at_name_default'.'attribute_id' = '65') AND 'at_name_default'.'store_id' = 0 LEFT JOIN 'catalog_product_entity_varchar' AS 'at_name' ON ('at_name'.'entity_id' = 'e'.'entity_id') AND ('at_name'.'attribute_id' = '65') AND ('at_name'.'store_id' = 1) INNER JOIN 'catalog_product_index_price' AS 'price_index' ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0 WHERE (link_table.parent_id = 3781) AND (IF(at_name.value_id > 0, at_name.value, at_name_default.value) LIKE '%PCL Labels%')'
try
$collection->getSelect()->order(new Zend_Db_Expr('quantity' *1));
In the end I achieved this in PHP via ksort(). The database model when implementing any Zend functions was being overridden somewhere and I couldn't afford the time to figure it out.