I have a function "fnc_FindIssueId" which accepts an object id and return its assigned issue Id.
When I call the function using pure select statements, it works fine:
select fnc_FindIssueId(150083); // returns 1 as issueId for objectId of 150083
select fnc_FindIssueId(150072); // returns 2 as issueId for objectId of 150072
But when I use it within an Inner Join, it goes into a never-ending loop:
select so.id, si.id
from smart_objects as so
LEFT OUTER join smart_issues as si
on si.id = fnc_FindIssueId(so.id)
where so.id in (150083, 150072);
What's the reason and how to resolve it?
It does not perform never-ending loop.
The reason for that is because the server performs FULL TABLE SCAN which is very slow. This condition si.id = fnc_FindIssueId(so.id) doesn't use an index even if you have define one on si.id and so.id.
The best ways you can do are:
to alter the table smart_objects
another column for the assigned issue Id
define an index on the new column
The workaround was to create a new view with ObjectId and IssueId columns then calling that function from within that view! but it has become very slow now.
CREATE ALGORITHM=UNDEFINED DEFINER=`mysql`#`%` SQL SECURITY DEFINER VIEW `vw_smart_objectissue` AS select `so`.`id` AS `objectid`,`fnc_FindIssueId`(`so`.`id`) AS `issueid` from `smart_objects` `so` order by `so`.`id`$$
Related
I have a query where i have "TEST"."TABLE" LEFT JOINED to PUBLIC."SchemaKey". Now in my final select statement i have a case statement where i check if c."Type" = 'FOREIGN' then i want to grab a value from another table but the table name value i am using in that select statement is coming from the left joined table column value. I've tried multiple ways to get to work but i keep getting an error, although if i hard code the table name it seems to work. i need the table name to come from c."FullParentTableName". Is what i am trying to achieve possible in snowflake and is there a way to make this work ? any help would be appreciated !
SELECT
c."ParentColumn",
c."FullParentTableName",
a."new_value",
a."column_name"
CASE WHEN c."Type" = 'FOREIGN' THEN (SELECT "Name" FROM TABLE(c."FullParentTableName") WHERE "Id" = 'SOME_ID') ELSE null END "TestColumn" -- Need assistance on this line...
FROM "TEST"."TABLE" a
LEFT JOIN (
select s."Type", s."ParentSchema", s."ParentTable", s."ParentColumn", concat(s."ParentSchema",'.','"',s."ParentTable",'"') "FullParentTableName",s."ChildSchema", s."ChildTable", trim(s."ChildColumn",'"') "ChildColumn"
from PUBLIC."SchemaKey" as s
where s."Type" = 'FOREIGN'
and s."ChildTable" = 'SOMETABLENAME'
and "ChildSchema" = 'SOMESCHEMANAME'
) c
on a."column_name" = c."ChildColumn"
Thanks !
In Snowflake you cannot dynamically use the partial results as tables.
You can use a single bound value via identifier to bind a value to table name
But you could write a Snowflake Scripting but it would need to explicitly join the N tables. Thus if you N is fixed, you should just join those.
I have been observed ActiveRecord delete_all is ignoring the joins table condition. Is this known issue from rails community?
Query:
DesignPartCategory.joins(:category).where(category: {site_id: INDIA}, designpart_uuid: ['123C']).delete_all
Expected result:
DELETE FROM designpart_category WHERE designpart_category.designpart_uuid IN ('123C') AND designpart_category.category_id IN (INDIA);
Actual Result:
DELETE FROM `designpart_category` WHERE `designpart_category`.`designpart_uuid` IN (SELECT designpart_uuid FROM (SELECT `designpart_category`.`designpart_uuid` FROM `designpart_category` INNER JOIN `category` ON `category`.`category_id` = `designpart_category`.`category_id` WHERE (category.site_id =INDIA AND designpart_category.designpart_uuid in ('123C'))) __active_record_temp);
Currently delete_all operation just ignoring/discards the joins table condition and executing the rest of the query.
I'm assuming it should not be the case, it should throw the exception instead of ignoring joins. Please let us know your thoughts/comments on it.
Seems there is some typo in your syntax, checkout this -
DesignPartCategory.joins(:category).where("categories.site_id = ? AND categories.designpart_uuid IN (?)", 'INDIA', ['123C']).delete_all
Alternatively you can try this: -
DesignPartCategory.joins(:category).where(categories: {site_id: 'INDIA', designpart_uuid: (['123C'])}).delete_all
Note: - Delete vs Destroy
Have you checked following in your query?
DELETE FROM `designpart_category`
WHERE `designpart_category`.`designpart_uuid` IN (
SELECT designpart_uuid FROM (
SELECT `designpart_category`.`designpart_uuid`
FROM `designpart_category` INNER JOIN `category`
ON `category`.`category_id` = `designpart_category`.`category_id`
WHERE (category.site_id =INDIA AND designpart_category.designpart_uuid in ('123C')
)
) __active_record_temp
);
It filters as per your join query, check query fired in IN
delete_all Deletes the records matching conditions without instantiating the records first, and hence not calling the destroy method nor invoking callbacks. So it will not take anything into account like join, includes etc...
Check the documentation
I can successfully join two tables, but i'm trying to output the results of the join into a new table.
The following throws a syntax error, but works if the "into" line is omitted.
To be clear - not having problems w/ the join, but the "into" statement.
SELECT evictions.uniqueid_neighborhoods.id, evictions.uniqueid_neighborhoods.neighbor_1,
evictions.sanfrancisco_evictions_backup2.Breach,
evictions.sanfrancisco_evictions_backup2.NonPayment,
evictions.sanfrancisco_evictions_backup2.Nuisance,
evictions.sanfrancisco_evictions_backup2.IllegalUse
** This causes code to fail
into evictions_by_commArea
from evictions.uniqueid_neighborhoods
inner join evictions.sanfrancisco_evictions_backup2 on evictions.uniqueid_neighborhoods.id = evictions.sanfrancisco_evictions_backup2.id
MySQL uses CREATE TABLE AS:
CREATE TABLE evictions_by_commArea as
SELECT un.id, un.neighbor_1,
sfe.Breach,
sfe.NonPayment,
sfe.Nuisance,
sfe.IllegalUse
from evictions.uniqueid_neighborhoods un join
evictions.sanfrancisco_evictions_backup2 sfe
on un.id = sfe.id;
I also introduced able aliases so the query is easier to write and to read.
I hava three tables called t_asset,t_device and t_asset_device.The relationship between t_asset and the t_device is multiple pairs.Each table column is :
t_asset :id , asset_name,asset_code,create_time,creator
t_device:id, device_name,device_code,latitude,longitude,create_time,creator
t_assets_device:id,asset_id,device_id,create_time,creator
Now I want to get all the t_asset and the latitude,longitude of the first device,So I write the code and function like these:
fun_getLatitudeByAssetId(`assetId` varchar(50)){
BEGIN
declare v_latituede DECIMAL(10,5) DEFAULT(-1) ;
select latitude into v_latituede
from t_device tDevice
inner join t_assets_device tAssetsDevice
on tAssetsDevice.asset_id=assetId and
tDevice.id=tAssetsDevice.device_id
and tDevice.latitude!=-1
ORDER BY tDevice.id desc
limit 0,1;
return v_latituede;
END
}
fun_getLongititueByAssetId(`assetId` varchar(50)){
BEGIN
declare v_longititue DECIMAL(10,5) DEFAULT(-1) ;
select longititueinto v_longititue
from t_device tDevice
inner join t_assets_device tAssetsDevice
on tAssetsDevice.asset_id=assetId and
tDevice.id=tAssetsDevice.device_id
and tDevice.latitude!=-1
ORDER BY tDevice.id desc
limit 0,1;
return v_longititue ;
END
}
The final query sql is:
select tAsset.*,fun_getLatitudeByAssetId(tAsset.id) latitude,
fun_getLongititueByAssetId(tAsset.id) longititue from t_asset tAsset
It seems that I have query the latitude and longititue two times,If I want to get the other field from the t_device,I do not want to write another function
like fun_getDeviceCodeByAssetId, How can I optimized my code?
I don't think a function or procedure is the way to go - why not just define a view that has asset_id + all the other fields you want? Then just join to it on asset_id rather than calling functions. In addition to just being cleaner, I'd be concerned about performance with row rather than set processing with the function approach (this is total speculation, I don't have deep enough knowledge of MySQL to know how it's handled)
Is it really necessary to do it with functions?
You can do it with views, for example:
create view latitudeLongitude as
select latitude,longitude,asset_id
from t_device tDevice
inner join t_assets_device tAssetsDevice
on tDevice.id=tAssetsDevice.device_id
and tDevice.latitude!=-1;
Finally your last select should look like this:
select tAsset.*,latitudeLongitude.latitude,
latitudeLongitude.longititue
from t_assettAsset inner join latitudeLongitude
on t_assettAsset.id = latitudeLongitude.asset_id
If you're trying to return several values at once then you should rather declare a stored procedure, not a function. Then you'll be able to write select latitude, longitude from ... inside your procedure and then call it with a command like call getLatAndLong(...)
In MySQL, I have defined a view on two tables as follows:
delimiter $$
CREATE ALGORITHM=UNDEFINED DEFINER=`root`#`localhost`<br/>
SQL SECURITY DEFINER VIEW `test`.`viewinschrijvingen` AS<br/>
select `i`.`student` AS `student`,<br/>
`i`.`opleidingscode` AS `opleidingscode`,<br/>
`i`.`inschrijvingsvorm` AS `inschrijvingsvorm`,<br/>
`i`.`brin` AS `brin`,<br/>
`i`.`brinvolgnummer` AS `brinvolgnummer`,<br/>
`o`.`onderwijsvorm` AS `onderwijsvorm`,<br/>
`o`.`opleidingniveau` AS `opleidingniveau`,<br/>
`o`.`naamopleidingkort` AS `naamopleidingkort`,<br/>
`o`.`instelling` AS `instelling`,<br/>
`o`.`studielast` AS `studielast`,<br/>
date_format(max(str_to_date(`i`.`datuminschrijving`,'%Y-%m-%d')),'%Y-%m-%d') AS `datuminschrijving`,<br/>
`o`.`gemeentenaam` AS `gemeentenaam` from<br/>
(`test`.`inschrijvingen` `i` left outer join `test`.`opleidingen` `o`<br/>
on((`i`.`opleidingscode` = `o`.`opleidingscode`)))<br/>
group by `i`.`opleidingscode`,`i`.`brin`,`i`.`brinvolgnummer`$$<br/>
When I query this view for the information on a specific student:
SELECT * FROM test.viewinschrijvingen WHERE student = '310018717'
the result is empty (no records returned). When I browse through the records in the view, there is no record for student 310018717 (obviously).
However, when I execute the query I used to create the view directly:
select `i`.`student` AS `student`,<br/>
`i`.`opleidingscode` AS `opleidingscode`,<br/>
`i`.`inschrijvingsvorm` AS `inschrijvingsvorm`,<br/>
`i`.`brin` AS `brin`,<br/>
`i`.`brinvolgnummer` AS `brinvolgnummer`,<br/>
`o`.`onderwijsvorm` AS `onderwijsvorm`,<br/>
`o`.`opleidingniveau` AS `opleidingniveau`,<br/>
`o`.`naamopleidingkort` AS `naamopleidingkort`,<br/>
`o`.`instelling` AS `instelling`,<br/>
`o`.`studielast` AS `studielast`,<br/>
date_format(max(str_to_date(`i`.`datuminschrijving`,'%Y-%m-%d')),'%Y-%m-%d') AS `datuminschrijving`,<br/>
`o`.`gemeentenaam` AS `gemeentenaam` from<br/>
(`test`.`inschrijvingen` `i` left outer join `test`.`opleidingen` `o`
on((`i`.`opleidingscode` = `o`.`opleidingscode`)))<br/>
WHERE student = '310018717'<br/>
group by `i`.`opleidingscode`,`i`.`brin`,`i`.`brinvolgnummer`<br/>
I do get a result (1 record, which is the result I expected). Can anybody help me to find what is causing this behaviour?
It probably has to do with your use of MySQL's GROUP BY extension versus the ANSI GROUP BY format. MySQL does not require you to group on every column that is not an aggregate function. For columns that you are not GROUPing on, MySQL can choose whatever value it wants for the column. In your case, you are not using the student field to group and thus it may not be choosing the value you are searching for.
You may want to try this query which uses the ANSI GROUP BY and see if you get the results you want.
delimiter $$
CREATE ALGORITHM=UNDEFINED DEFINER=`root`#`localhost`
SQL SECURITY DEFINER VIEW `test`.`viewinschrijvingen` AS
select
`i`.`student` AS `student`,
`i`.`opleidingscode` AS `opleidingscode`,
`i`.`inschrijvingsvorm` AS `inschrijvingsvorm`,
`i`.`brin` AS `brin`,
`i`.`brinvolgnummer` AS `brinvolgnummer`,
`o`.`onderwijsvorm` AS `onderwijsvorm`,
`o`.`opleidingniveau` AS `opleidingniveau`,
`o`.`naamopleidingkort` AS `naamopleidingkort`,
`o`.`instelling` AS `instelling`,
`o`.`studielast` AS `studielast`,
date_format(max(str_to_date(`i`.`datuminschrijving`,'%Y-%m-%d')),'%Y-%m-%d') AS `datuminschrijving`,
`o`.`gemeentenaam` AS `gemeentenaam`
from `test`.`inschrijvingen` `i`
left outer join `test`.`opleidingen` `o`
on `i`.`opleidingscode` = `o`.`opleidingscode`
group by
`i`.`student`,
`i`.`opleidingscode`,
`i`.`inschrijvingsvorm`,
`i`.`brin` AS `brin`,
`i`.`brinvolgnummer`,
`o`.`onderwijsvorm`,
`o`.`opleidingniveau`,
`o`.`naamopleidingkort`,
`o`.`instelling`,
`o`.`studielast`,
`o`.`gemeentenaam`$$