How to group overlapping data in SQL - 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.

Related

Convert Salesforce IDs from 15 digit to 18 digit using sql code/function

We are currently pulling in data from SalesForce to SQL Database tables. There are 2 custom fields on different objects that were created for the Lead ID and a look up for which event/task is linked (this can be an account id, contact id, or lead id). Both of these are pulling over the 15 digit ID.
I am trying to find out if there is any SQL code or a SQL function that will allow me to convert that 15 digit to an 18 digit ID.
I need to have that 18 digit ID to join back to the other objects.
We have already tried using the CASESAFEID(Id) function in SalesForce, but with the API that was already set up and the visibility levels our particular ETL is not showing that field. Also, we would need to get a consultant to mess with the look up column.
I would like to take the 15 digit ID and convert it to the 18 digit code. If the SalesforceID is 0035000002tAzbu, how do I get the converted 18 digit value to be 0035000002tAzbuACC. I need to get that last 3 digits using SQL query or SQL function.
you could write a custom function in your sql database.
e.g. in snowflake, you can make a function like this
CREATE OR REPLACE FUNCTION dw.my_schema.f_sfdc_ch15_to_ch18("txt" string)
RETURNS string
LANGUAGE JAVASCRIPT
AS '
if ( txt == undefined || txt == "" || typeof txt == "undefined" || txt == null) {
return ;
} else {
var id15, id18;
if (txt.length == 18) {
return txt;
} else if (txt.length == 15) {
id15 = [txt.trim()];
} else {
return "";
}
for ( var x=0; x < id15.length; x++ ) {
var s = "";
for ( var i=0; i<3; i++) {
var f = 0;
for (var j=0; j<5; j++) {
var c = id15[x].charAt(i*5+j);
if (c>="A" && c<="Z") {
f+=1<<j;
}
}
s += "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345".charAt(f);
}
id18 = id15[x]+s;
}
}
return id18.toString();
';
and use it like this
select dw.my_schema.f_sfdc_ch15_to_ch18(id15) from mytable;
This value can be computed. Check out this flowchart.
Source: https://stackoverflow.com/a/29299786/3135974

SQLite with Android Studio, return all records selected by 2 arguments

let's assume that i have a table with columns such as:
ID SSID BSSID RSSI
1 abcd hs:hd:sd -60
2 abcd hs:hd:po -68
There are about 5000 records with the same SSID, slighltly different BSSID and the LEVEL values. My device is scanning the nearest environment for WiFi networks, therefore I know their MAC address and level of RSSI. I pick 3 with the highest value od RSSI.
First thing I would like to know if it is possible to search through the database to get all the records with the LEVEL value equal or close to 60, for instance 59,58,61.
Secondly, is there a way to query the database to return all the records with the same MAC addresses and RSSI values as from the 3 best scan result? If so, how would that query look like?
EDIT: Thanks for all the answers. What I'm trying to do now is to compare 3 scans with records stored in database with getRequiredData function. I would like to pass 2 parameters to this function, mac address and level and find records with same value for both parameters. The rawQuery seems to be fine, code is compiling but the app is crashing with the first scan. I cant find the cause of it, is it because my logic of getting these parameters is wrong or does it have something to do with query?
public Cursor getRequiredData(String mac, int level){
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery("SELECT BSSID, RSSI FROM TABLE_NAME WHERE BSSID =? AND RSSI=?", new String[] {mac, level});
return res;
}
scan part:
class WifiReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
sb = new StringBuilder();
Comparator<ScanResult> comparator = new Comparator<ScanResult>() {
#Override
public int compare(ScanResult o1, ScanResult o2) {
return (o1.level>o2.level ? -1 : (o1.level==o2.level ? 0 : 1));
}
};
lista = wifiManager.getScanResults();
Collections.sort(lista, comparator);
for (int i = 0; i < lista.size(); i++) {
scanResult = wifiManager.getScanResults().get(i);
sb.append(new Integer(i + 1).toString() + ". " + (lista.get(i)).SSID + " " + (lista.get(i)).BSSID + " " + (lista.get(i)).level + "\n");
boolean isInserted = myDb.insertData(lista.get(i).SSID.toString(), lista.get(i).BSSID.toString(), lista.get(i).level);
if (isInserted = true)
Toast.makeText(MainActivity.this, "Data inserted", Toast.LENGTH_LONG).show();
else
Toast.makeText(MainActivity.this, "Data not inserted", Toast.LENGTH_LONG).show();
}
for (int i=0; i<4; i++)
{
scanResult = wifiManager.getScanResults().get(i);
match = myDb.getRequiredData(lista.get(i).BSSID.toString(), lista.get(i).level);
}
Log.i("match values: ", DatabaseUtils.dumpCursorToString(match));
txt.setText(sb);
wifiManager.startScan();
}
}
Here is what match contains:
2018-12-10 16:36:26.334 13347-13347/com.example.maciek.wifiscann I/match values:: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor#e1a86d1
0 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
1 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
2 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
3 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
4 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
5 {
BSSID=f4:c5:ed:5c:s6:20
RSSI=-69
}
<<<<<
To get the 3 rows with the closest values to 60 in column LEVEL:
SELECT * FROM tablename ORDER BY ABS(LEVEL - 60), LEVEL LIMIT 3
For the 2nd part of your question, you should provide sample data of the table. Edit:
From the sample data that you posted I don't see a column RSSI, but if it exists in the table then the SELECT statement is ok.
Change the 2nd parameter of rawQuery() to:
new String[] {mac, String.valueOf(level)}
because level is int.
In onReceive() you use myDb. I don't know how you initialize it.
If the app crashes you must copy the log, the part that identifies the problem and post it.
First thing I would like to know if it is possible to search through
the database to get all the records with the LEVEL value equal or
close to 60, for instance 59,58,61.
SELECT * FROM your_table WHERE level BETWEEN 59 AND 61;
where your_table is the respective table name.
Note if levels are negative (as per example data) then BETWEEN requires the lowest value first so it would be BETWEEN -61 AND -59.
Secondly, is there a way to query the database to return all the
records with the same MAC addresses and RSSI values as from the 3 best
scan result? If so, how would that query look like?
SELECT * FROM your_table WHERE your_mac_address_column = 'the_mac_address_value' AND RSSI = 'the_rssi_value' ORDER BY LEVEL DESC LIMIT 3
Note the above assumes that the MAC address is stored in a column (if NOT then cannot be done unless the mac address can be correlated to a column).
Assumes best LEVEL is lowest so -1 is better than -60 (if not then use ASC instead of DESC)
Again your_table, your_mac_address_column, the_mac_address_value and the_rssi_value would be replaced accordingly with actual values (note that strings should be in single quotes).

Why does this Linq Query Return Different Results than SQL Equivalent?

I'm sure I'm missing something simple but I have a linq query here:
public static List<Guid> GetAudience()
{
var createdOn = new DateTime(2018, 6, 30, 0, 0, 0);
var x = new List<Guid>();
try
{
var query = from acc in Account
where acc.num != null
&& acc.StateCode.Equals(0)
&& acc.CreatedOn < createdOn
select new
{
acc.Id
};
foreach (var z in query)
{
if (z.Id != null)
{
x.Add(z.Id.Value);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
return x;
}
I wanted to verify the count in SQL because it would only take a couple seconds so:
select count(*)
from Account a
where a.num is not null
and a.statecode = 0
and a.createdon < '2018-06-30 00:00:00'
And now the SQL query is returning 9,329 whereas Linq is returning 10,928. Why are my counts so far off when the queries are doing the same thing (so I thought)? What simple thing am I missing?
Thanks in advance--
Your method is returning a list of records where the Id values are not null (plus the other criteria). The SQL query is returning a count of the number of records (plus the other criteria). Without the definition of your table, it's hard to know whether that is significant.
Unrelated tip: it's not a good idea to catch and swallow exceptions like that - the caller of your method will have no idea that anything went wrong, so processing will continue; but it will be using incomplete data, potentially leading to other problems in your program later.

Pseudocode for SQL query

Hi guys i have the following question,
Assume tables foo(a int, b int) and bar(a int, b int) and assume you are given a stream ‘TableReader’ that reads rows from a table that has the following methods:
tr.next() returns the next row of a type ‘row’ from the stream if there is a next row or null if there are no more rows.
Assume columns can be accessed using row[columnName]. For example, to read rows from foo, you have to do the following:
foo_stream = TableReader(‘foo’);
row = foo_stream.next();
row[‘a’] will return the value of column a and row[‘b’] will return the value of column b.
Write a pseudocode to compute the results of the following SQL query which should return a list of rows:
select foo.a, foo.b, bar.a, bar.b
from foo, bar
where foo.a = bar.a
and foo.b <=100;
Can anyone help me on this ?
The solution i tried is:
Foo_stream = TableReader(‘foo’);
Bar_stream = tableReader(‘bar’);
While(foo_stream.next())
{
{
While(bar_stream.next())
{
Row_foo = foo_stream.next();
Row_Bar =bar_stream.next();
{
If((row_foo[a] equals row_bar[a]) AND (row_foo[b] < = 100))
{
Then print row_foo[a],row_foo[b], row_bar[a], row_bar[b]
}
}
}
}
But the above solution is of complexity O(n2), any better solution is appreciated.
Probably something like this:
Foo_stream = TableReader(‘foo’);
Foo_row = Foo_stream.next();
Foo_hash = New HashSet<Foo_row[a].typeof, Foo_row.typeof>();
Do
{
if (Foo_row[b] <= 100)
{
Foo_hash.Add(Foo_row[a], Foo_row);
}
if (!foo_stream.next()) { Foo_row = Foo_stream.next(); }
} While(foo_stream.next())
Bar_stream = tableReader(‘bar’);
While(bar_stream.next())
{
Bar_row = Bar_stream.next();
if (Foo_hash.Exists(Bar_row[a]))
{
Foo_row = Foo_hash(Bar_row[a]);
print foo_row[a],foo_row[b], bar_row[a],bar_row[b];
}
}
This is called the HashMap method, and is O(n), though it uses a relatively large amount of memory.
There is also the MergeSort method, which is O(NlogN) unless the streams are already sorted on [a]. It requires somewhat less memory than the HashMap method.
Finally there is the method that you used, which is called the Nested Loops method, and as you said, is O(n^2), but has the advantage of needing very little memory.

Convert SQL - LINQ - Problem with using both Min/Max

Is there a online system which converts SQL - LINQ or can anyone else help convert the SQL - LINQ below?
SELECT MIN(startTime) As startTime, MAX(endTime) As endTime
FROM tblRA
LEFT JOIN tblA ON tblRA.asID = tblA.asID
WHERE 'xxxxxx' BETWEEN tblRA.startDate AND tblRA.endDate
AND tblA.availabilityDayOfWeek = 7
The main area I am having trouble is the .MAX/.MIN.
Heres what I have so far
public List<string> GetResourceAvailabilitiesByDate(DateTime searchDate)
{
DayOfWeek dayOfWeek = searchDate.DayOfWeek;
var minVal = from a in dc.tblResourceAvailabilities
join b in dc.tblAvailabilities on a.asID equals b.asID
where searchDate.Date >= a.startDate.Date && searchDate.Date <= a.endDate.Value.Date
&& b.availabilityDayOfWeek == (int)dayOfWeek
select b.startTime.ToShortTimeString();;
var maxVal = from a in dc.tblResourceAvailabilities
join b in dc.tblAvailabilities on a.asID equals b.asID
where searchDate.Date >= a.startDate.Date && searchDate.Date <= a.endDate.Value.Date
&& b.availabilityDayOfWeek == (int)dayOfWeek
select b.endTime.ToShortTimeString();
var min = minVal.Min(minVal.Min);
var max = maxVal.Max();
return min,max;
Thanks in advance for any help
Clare
I think your code is a little bit incorrect, and the first symptom of it is that you are using repeated code to define minval and maxval. I tried to simulate something similar to what you want and came to the following code, please adapt it to your needs.
public List<string> GetResourceAvailabilitiesByDate(DateTime searchDate)
{
DayOfWeek dayOfWeek = searchDate.DayOfWeek;
var vals = from a in dc.tblResourceAvailabilities
join b in dc.tblAvailabilities on a.asID equals b.asID
where searchDate.Date >= a.startDate.Date && searchDate.Date <= a.endDate.Value.Date
&& b.availabilityDayOfWeek == (int)dayOfWeek
select b;
var min = vals.Min(v => v.startTime).ToShortTimeString();
var max = vals.Max(v => v.startTime).ToShortTimeString();
return new List<string>() { min, max };
}
Some comments on your code, assuming it's C#.
You are trying to return an array of strings when you should be returning an array of dates.
Your where clause is pretty confuse. You're comparing the search date with startdate.Date and endDate.Value.Date. It does not make much sense.
Your select clause could select only b, or a, or whatever. You don't really need to select the date in it.