How to replace query conditions in a loop in Laravel? - sql

I have a user table with name, status and distance. I want to get the users under a particular distance and if the result is empty I want to check it again with an incremented value.
$user = User::where('status',1);
$i = 10;
while($i < 50)
{
$user->having('distance', '<=', $i);
if($user->get()->count())
break;
$i = $i+5;
};
In the first loop I got the query correctly as SELECT * from users where status = 1 and having distance <= 10. If the result is empty in the second loop I got the query as SELECT * from users where status = 1 and having distance <= 10 and having distance <= 15. I want to get the query as SELECT * from users where status = 1 and having distance <= 15. What change should I do for this?

You are working here on objects and you should use clone:
$user = User::where('status',1);
$i = 10;
while($i < 50)
{
$query = (clone $user)->having('distance', '<=', $i);
if($query->get()->count())
break;
$i = $i+5;
}
In addition you are using:
$query->get()->count()
what causes that you get all records matching query from database and calculate their amount. If you just need to have their count, it's much better to use just:
$query->count()

Related

SnowFlake Query if an Id exists on each of the last 7 days

We INSERT new records every day to a table with say id and created_on column.
How do i identify if records with a particular identifier existed every day in the last 7 days ?
This can be done with a Stored Procedure:
CREATE OR REPLACE PROCEDURE TIME_TRAVEL(QUERY TEXT, DAYS FLOAT)
RETURNS VARIANT LANGUAGE JAVASCRIPT AS
$$
function run_query(query, offset) {
try {
var sqlText = query.replace('"at"', " AT(OFFSET => " + (offset + 0) + ") ");
return (snowflake.execute({sqlText: sqlText})).next();
}
catch(e) { return false }
}
var days, result = [];
for (days = 0; days < DAYS; days++)
if (run_query(QUERY, -days * 86400)) result.push(days);
return result;
$$;
CALL TIME_TRAVEL('SELECT * FROM TASK_HISTORY "at" WHERE QUERY_ID = ''019024ef-002e-8f71-0000-05e10030a782''', 7);
For the time travel query replace to work, put in an "at" as a table alias.
The return value is an array of day offsets when the query returns any value.
This will only work beyond DAYS=2 if you have Snowflake Enterprise Edition.
I did it with the below query
select id, sum(present) as total_count
from
(select id,feed_date, count(1) as present
from catalog_rca
where feed_date between '2019-11-19' and '2019-11-25'
group by 1,2) as temp
group by 1 having total_count = 7;

Qliksense Extension - Select Values

I need to pass the value 'A' to be selected into a Qliksense extension. This extension contains 1 dimension and 1 measure. I would like 'A' to be selected in the 1 dimension.
It seems that self.selectValues(0, 'A', false); is the call for this. I can't get this to work at all.
How do I select 'A' in this extension or the underlying table?
Details:
I have the following code inside the paint function that renders the data (this part works):
// iterate over all rows
var hc = layout.qHyperCube;
for (var r = 0; r < hc.qDataPages[0].qMatrix.length; r++) {
table += '<tr>';
// iterate over all cells within a row
for (var c = 0; c < hc.qDataPages[0].qMatrix[r].length; c++) {
table += '<td>';
table += hc.qDataPages[0].qMatrix[r][c].qText;
table += '</td>';
}
table += '</tr>';
}
Method expects an array and the element number of the dimension value, so this should work:
self.selectValues(0, [qElemNumber], false);

How to group overlapping data in SQL

I have data in following fashion
Prog_Id Low_latency Max_Latency
a 1 4
a -1 5
a 3 8
a 11 12
a 12 15
Now I wish to see output as
Prog_Id Low_latency Max_Latency
a -1 8
a 11 15
Basically I wish to merge overlapping data. Can anyone help me with the code. I can manage time at the place of latency, if there is a solution with OVERLAPS clause.
Thanks
Rishabh
My initial answer was not always working. Now it looks like it is:
select distinct *
from (
select
t1.Prog_ID,
min(least(l, Low_latency)),
max(greatest(g, Max_Latency))
from yourtable t1 inner join (select
t1.Prog_ID,
least(t1.Low_latency, t2.Low_latency) l,
greatest(t1.Max_Latency, t2.Max_Latency) g
from
yourtable t1 inner join yourtable t2
on t1.Prog_ID=t2.Prog_ID
and t1.Low_latency<=t2.Max_Latency
and t1.Max_Latency>=t2.Low_Latency) t2
on t1.Prog_ID=t2.Prog_ID
and t1.Low_latency<=t2.g
and t1.Max_Latency>=t2.l
group by t1.Low_latency, t1.Max_latency) s
please see here. It's MySql code but can be converted for other DBMS.
It depends on which databse server (DBMS) you use. But there is no easy solution for. There could be a possibility to use Stored procedures . But I would prefer to do this in a programming language (which language do you use?)
After testing some around with querys of other people, I found no way in SQL.
Here is something simular to map reduce in java
public class YourData {
Double Low_latency;
Dobule Max_Latency;
int Prog_Id;
// add getter and setter here
public boolean tesetOverlapping(YourData data) {
if ((this.Low_latency<=data.Low_latency && data.Low_latency<=t1.Max_Latency) ¦¦ (this.Low_latency<=data.Max_Latency && data.Max_Latency<=this.Max_Latency)) {
this.Low_latency = Math.min(this.Low_latency, data.Low_latency);
this.Max_Latency = Math.min(this.Max_Latency, data.Max_Latency);
return true
}
return false;
}
}
String sql = "
SELECT
t1.Prog_Id,
t1.Low_latency,
t1.Max_Latency
FROM yourtable t1"
ArrayList<ArrayList<Double>> values = new ArrayList<ArrayList<Double>>();
while (row = get sql rows) {
int progIndex = values.indexOf(row.Prog_Id);
if (progIndex == -1) {
progIndex = values.indexOf(row.Prog_Id);
values.add(progIndex, new ArrayList<Double>());
}
values[progIndex].add(new YourData(row));
}
boolean foundOverlapping = false;
for (int progIndex = 0; progIndex < values.size(); progIndex++) {
// Do map reduce for each progIndex
do {
foundOverlapping = false;
for (int i = 0; i < values[progIndex].size(); i++) {
if (!values[progIndex].contains(i)) {
continue;
}
YourData cur = values[progIndex][i];
for (int x = 0; x < values[progIndex].size(); x++) {
if (i != x && values[progIndex].contains(x)) {
if (cur.tesetOverlapping(values[progIndex][x])) {
foundOverlapping = true;
values[progIndex].remove(x);
}
}
}
}
} while (foundOverlapping == true);
}
Assuming you want to group in a -infinity...9, 10...19, 20...29 pattern for the lower latency, you would need something like
SELECT
Prog_Id,
MIN(Low_latency) AS Low_latency,
MAX(Max_Latency) AS Max_Latency
FROM
your_table_name
GROUP BY
Prog_Id,
IF(FLOOR(Low_latency/10)<0,0,FLOOR(Low_latency/10))
Obviously the last line will depend on the RDBMS used, but should be quite similar among most.
You might also want to add an ORDER BY clause.

how to get the second batch and 3rd batch in the same query result in oracle sql + yii framework?

let' say i have 20 results in the sql query. if am gonna use the limit in the yii active record, I'll obviously get the first four from the result, but what if i wanna get the 2nd four and then 3rd four in the same query result ? how to query that via sql ?
e.g
$criteria2 = new CDbCriteria();
$criteria2->select = 'USERID, ADID ,ADTYPE, ADTITLE, ADDESC, PAGEVIEW, DISPPUBLISHDATE';
$criteria2->addCondition("STATUS = 1");
$criteria2->order = '"t".PAGEVIEW DESC,"t".PUBLISHDATE DESC';
$criteria2->limit = 4;
$criteria2->with = array('subcat','adimages');
$result = $this->findAll($criteria2);
return $result;
Sorry :)
See here, how to paginate with Oracle (Are you use 11g?)
Alternatives to LIMIT and OFFSET for paging in Oracle
Well and in Yii just set offset, OCIConnector will set rownum automaticly for sql
$criteria2 = new CDbCriteria();
$criteria2->select = 'USERID, ADID ,ADTYPE, ADTITLE, ADDESC, PAGEVIEW, DISPPUBLISHDATE';
$criteria2->addCondition("STATUS = 1");
$criteria2->order = '"t".PAGEVIEW DESC,"t".PUBLISHDATE DESC';
$criteria2->limit = 4;
$criteria2->offset = 0; //4, 8 - COciCommandBuiled applyLimit use it
$criteria2->with = array('subcat','adimages');
$result = $this->findAll($criteria2);
return $result;

SQL date comparison in WHERE clause, TypoScript

I want to compare dates in a TypoScript select.
Here's what I have (note that I commented the were clauses) :
lib.my_val = CONTENT
lib.my_val {
select {
pidInList = 100000
max = 1
#where = effective_date < CURDATE()
#where = TIMESTAMP(effective_date) < NOW()
orderBy = effective_date DESC
}
table = tx_my_table
renderObj = COA
renderObj {
5 = TEXT
5{
field = my_field
wrap = <span>|</span>
}
[...]
}
}
Which returns lines.
I tried to add a where statement any way I could with static dates or variables... without success. My understanding of the where clause is that everything after the = is dumped as is in the SQL query. But it seems I missed something.
Basically I want the TypoScript to generate a SQL Query smilar to this :
SELECT * FROM tx_my_table WHERE effective_date < NOW() ORDER BY effective_date DESC LIMIT 1;
This should be simple. Has anyone done this in the past?
Thanks!
Your TypoScript seems to be OK.
What happens if you enter the SQL Query directly into MySQL?
Note that with your code, only one record with pid=100000 is
selected.
Have you tried this:
--
lib.my_val {
select {
pidInList = 100000
max = 1
where = UNIX_TIMESTAMP(effective_date) < UNIX_TIMESTAMP()
orderBy = UNIX_TIMESTAMP(effective_date) DESC
}
table = tx_my_table
}
TYPO3 Wiki on select