How can I do sql union in cake php? - sql

I have to get all the associative data for the model. Basically the UNION query is as below:
SELECT * FROM `videos` AS `U1`
WHERE `U1`.`level_id` = '1' AND `U1`.`submitted_date` > '2011-09-11'
UNION
SELECT * FROM `videos` AS `U2`
WHERE `U2`.`level_id` = '1' AND `U2`.`submitted_date` < '2011-09-11'
ORDER BY submitted_date DESC
LIMIT 0,10
So when I use
$this->Video->find('all')--> I get all the result of the associated table datas.
Now I want to use the UNION SQL query and that should return associated table data too...
Any ideas how to use the cake inbuilt function to get data?

You can do this in 4 or more different ways... the easiest but not recomended is using
$this->Model->query($query);
where $query is the query stated above.
The second way but may not be what you want, is to redo your sql query you will get same result (but not separated with the alias) like this:
SELECT * FROM `videos` AS `U1`
WHERE `U1`.`level_id` = '1' AND (`U1`.`submitted_date` > '2011-09-11' OR `U1`.`submitted_date` < '2011-09-11')
ORDER BY submitted_date DESC
LIMIT 0,10
This query can be easily done with find like this
$conditions = array(
'Video.level_id'=>1,
'OR' => array(
'Video.submitted_date <'=> '2011-09-11',
'Video.submitted_date >'=> '2011-09-11'
)
);
$this->Video->find('all', array('conditions'=>$conditions))
The third way will be the one that Abba Bryant talk about, explained in detail here Union syntax in cakePhp that works building the statement directly.
The fourth way will like the first one more less, you will have to create a behaviour that have a beforeFind function and there you will have to check if a option union and create the query or to create something like the the third option.
you will call it with a find like this
$this->Video->find('all', array('conditions'=>$conditions, 'union'=> $union));
This will be something more less like the linkable or containable behavior.
The fith way is to modified your cakephp sql driver... this one, i don't really know the changes you have to do, but it is a way to get to that... This drivers are the responsible to interpret and create the queries, connect to db and execute the queries...
REMEMBER that cakephp find do the checks neccesary to prevent SQLInyection and other risks... the $model->query will NOT do this tests so be carefull

This question here uses joins and the some direct datasource access to build a union query that can be used via the find method.
It is a bit of work, and the code won't be 100% appropriate for you - you will have to modify it - but it should get you started.
UNION syntax in Cakephp

Related

Query Snowflake Jobs [duplicate]

is there any way within snowflake/sql query to view what tables are being queried the most as well as what columns? I want to know what data is of most value to my users and not sure how to do this programatically. Any thoughts are appreciated - thank you!
2021 update
The new ACCESS_HISTORY view has this information (in preview right now, enterprise edition).
For example, if you want to find the most used columns:
select obj.value:objectName::string objName
, col.value:columnName::string colName
, count(*) uses
, min(query_start_time) since
, max(query_start_time) until
from snowflake.account_usage.access_history
, table(flatten(direct_objects_accessed)) obj
, table(flatten(obj.value:columns)) col
group by 1, 2
order by uses desc
Ref: https://docs.snowflake.com/en/sql-reference/account-usage/access_history.html
2020 answer
The best I found (for now):
For any given query, you can find what tables are scanned through looking at the plan generated for it:
SELECT *, "objects"
FROM TABLE(EXPLAIN_JSON(SYSTEM$EXPLAIN_PLAN_JSON('SELECT * FROM a.b.any_table_or_view')))
WHERE "operation"='TableScan'
You can find all of your previous ran queries too:
select QUERY_TEXT
from table(information_schema.query_history())
So the natural next step would be combine both - but that's not straightforward, as you'll get an error like:
SQL compilation error: argument 1 to function EXPLAIN_JSON needs to be constant, found 'SYSTEM$EXPLAIN_PLAN_JSON('SELECT * FROM a.b.c')'
The solution would be to combine the queries from the query_history() with the SYSTEM$EXPLAIN_PLAN_JSON outside (to make the strings constant), and then you will be able to find out the most queried tables.

How to query only old and duplicate data from a database in SQL

I'm trying to query my database to pull only duplicate/old data to write to a scratch section in excel (Using a macro passing SQL to the DB).
For now, I'm currently testing in Access alone to only filter out the old data.
First, I'm trying to filter my database by a specifed WorkOrder, RunNumber, and Row.
The code below only filters by Work Order, RunNumber, and Row. ...but SQL doesn't like when I tack on a 2nd AND statement; so this currently isn't working.
SELECT *
FROM DataPoints
WHERE (((DataPoints.[WorkOrder])=[WO2]) AND ((DataPoints.[RunNumber])=6) AND ((DataPoints.[Row]=1)
Once I figure that portion out....
Then if there is only 1 entry with specified WorkOrder, RunNumber, and Row, then I want filter it out. (its not needed in the scratch section, because its data is already written to the main section of my report)
If there are 2 or more entries with said criteria(WO, RN, and Row), then I want to filter out the newest entry based on RunDate and RunTime, and only keep all older entries.
For instance, in the clip below. The only item remaining in my filtered query will be the top entry with the timestamp 11:47:00AM.
.
Are there any recommended commands to complete this problem? Any ideas are helpful. Thank you.
I would suggest something along the lines of the following:
select t.*
from datapoints t
where
t.workorder = [WO2] and
t.runnumber = 6 and
t.row = 1 and
exists
(
select 1
from datapoints u
where
u.workorder = t.workorder and
u.runnumber = t.runnumber and
u.row = t.row and
(u.rundate > t.rundate or (u.rundate = t.rundate and u.runtime > t.runtime))
)
Here, if the correlated subquery within the where clause finds a record with the same workorder, runnumber and row, but with either a later rundate or the same rundate and a later runtime, then the record is returned by the main query.
You need two more )'s at the end of your code snippet. Or you can delete the parentheses completely in this example, MS Access will ad them back in as it deems necessary.
M.S. Access SQL can be tricky as it is not standards compliant and either doesn't allow for super complex queries, or it needs an ugly work around, like having a parentheses nesting nightmare when trying to join more than two tables.
For these reasons, I suggest using multiple Access queries to produce your results.

Oracle DB Query Custom Order by

I'm looking for a way to accomplish something kind of like fuzzy search with Oracle. If this has already been answered, I'll gladly accept a link, but I'm so new to Oracle that I'm not even sure how to quickly search for what I want.
Given the following query:
SELECT VEND_CUST_CD, LGL_NM, ALIAS_NM
FROM {{DB_NAME}}.{{DB_TABLE}}
WHERE ({{condition_1}}) AND ({{condition_2}}) AND (upper(LGL_NM) LIKE upper('%{{term}}%')
ORDER BY LGL_NM
What I'd like to get in my response is a particular order. Let's imagine term=ze for the purposes of this.
I'd like to get results ordered like so:
Zealot Johnson
Zebra Eaters
Zero Gravity
Amazed John
Bedazzel
Lazer Sex
Zazew
So that what I'm getting back first is words that start with term followed by an alphabetical list of words that contain term within them.
I hope this is clear.
I suppose you can order the results like so:
ORDER BY CASE WHEN LGL_NM LIKE '{{term}}%' THEN 1 ELSE 2 END, LGL_NM
You can use union all like this:
select * from (
SELECT VEND_CUST_CD, LGL_NM, ALIAS_NM
FROM {{DB_NAME}}.{{DB_TABLE}}
WHERE ({{condition_1}}) AND ({{condition_2}}) AND (upper(LGL_NM) LIKE upper('{{term}}%')
union all
SELECT VEND_CUST_CD, LGL_NM, ALIAS_NM
FROM {{DB_NAME}}.{{DB_TABLE}}
WHERE ({{condition_1}}) AND ({{condition_2}}) AND (upper(LGL_NM) LIKE upper('{{%term%}}') AND (upper(LGL_NM) not LIKE upper('{{term%}}')
) order by ...
or like #Salman A 's way

BigQuery can use wildcard table names and table_suffix, but I am looking for a similar solution like wildcard datasets and dataset_suffix

So if you process data daily and put the results into the same dataset, such as results, and each day will have the same table name (first part) and with date as table_suffix, such as result1_20190101, result1_20190102 etc., they you query the result tables use wildcard table names and table_suffix.
So your dataset/tables looks like
results/result1_20190101
results/result1_20190102
results/result2_20190101
results/result2_20190102
So I can query all the result1
select * from `xxxx.results.result1*`
But I arrange the results tables differently. Due to I have dozens tables processed each day. so to easily check and manage each day results. I use date as dataset.
so my dataset/tables look like
20190101/result1
20190101/result2
...
20190102/result1
20190102/result2
...
And my daily data process usually will not query cross dates(datasets). the daily results are pushed to next step data pipelines etc.
But once a while, I need to do some quick check, and I need to query across the dates(in my case, across the datasets)
so when I try to query result1, I have to hard code the dataset name.
select * from `xxxxxx.20190101/result1`
union all
select * from `xxxxxx.20190102/result1`
union all
...
1) First question is, are there anyway I could use wildcards and suffix on datasets, like we could with tables?
2) Second question: how could I use the date function, such as DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY) to get the date value and use the data value in the below query
select * from `xxxxxx.20190101/result1`
union all
select * from `xxxxxx.20190102/result1`
union all
...
to replace the hard coded value, 20190101, 20190102 etc.
There is no wildcards and/or suffix available on BigQuery datasets (at least as of today)
Meantime, you can check a feature request for INFORMATION_SCHEMA that is in Alpha now. You can apply for it by submitting form that is available there.
In short: you will be able to query list of datasets in the projects and then use it to construct your query. Please note - you still need to use some sort of client to script all this properly

Limit 1 should be used with queryRow in Yii?

I am usually using queryRow to get a single record. eg:-
$lastReport = Yii::app()->db->createCommand(
'SELECT * FROM report ORDER BY created DESC'
)->queryRow();
I looked the MySQL log to know which query is used for it.
SELECT tbl_report.* FROM report ORDER BY created DESC
It seems that Yii is retrieving all the records from the table and return the first record.
So I think we should use LIMIT 1 whenever we are using queryRow. eg:-
$lastReport = Yii::app()->db->createCommand(
'SELECT * FROM report ORDER BY created DESC LIMIT 1'
)->queryRow();
Since the queryRow is returning "the first row (in terms of an array) of the query result", Yii should automatically add the limit. otherwise user will use this query to get a single record and that will cause to performance degradation.
Is my understanding is correct or I missed something?
Yii should not add limit 1 to query, because queryRow is designed to get results row by row, for example in while. Yii has limited functionality with raw SQL code, but Query Builder is available:
$user = Yii::app()->db->createCommand()
->select('id, username, profile')
->from('tbl_user u')
->join('tbl_profile p', 'u.id=p.user_id')
->where('id=:id', array(':id'=>$id))
->queryRow();
More information available here: http://www.yiiframework.com/doc/guide/1.1/en/database.query-builder
You should rather use ActiveRecordClassName::model()->findByPk($id); or ActiveRecordClassName::model()->find($criteria), because it uses defaultScope() and other improvements.