'extend' operator: Failed to resolve scalar expression named 'd' - kql

I'm struggling with the following problem in KQL,
let a = 1;
let b = 2;
let c = DeviceInfo
| take 3
| count
| project-rename c=Count;
let d = DeviceInfo
| take 4
| count
| project-rename d=Count;
c | extend a,b
This produce the following result
| c | a | b |
-------------
| 3 | 1 | 2 |
By changing the last line, I'm able to get a,b,d but I'm unable to get a,b,c,d in the same table. I get the
'extend' operator: Failed to resolve scalar expression named 'd'
Any clues ? How can we use multiples let variable who come from results in a single table ?

try this simplified and clearer version, using toscalar():
let a = 1;
let b = 2;
let c = toscalar(
DeviceInfo
| take 3
| count
);
let d = toscalar(
DeviceInfo
| take 4
| count
);
print a, b, d, c

Related

Query to fetch superset if subset combination returns null result?

TABLE : **PROFILE**
RUN_ID| Type | code | gender | vacId
1 | A | biz | M | 110
2 | A | pro | M | 113
3 | A | tot | F | 114
Required to return the vacId, based on the input if I input, if code+type combination is not present then return only vacId which equals to given type
TYPE=A AND CODE=BIZ AND GENDER=M , then it should return 110
TYPE=A AND CODE=SYS then should return 110 & 113 , 114 there is no A+SYS combination so returned superset A's data
How can I write a query for this which should work in pgsql and oracle for now.
Is there a way that I can achieve this using COALESCE
You can use conditional where clause, e.g. ($ used for parameters):
select p.*
from profile p
where case
when exists (
select 1
from profile
where type = $type and code = $code and gender = $gender
)
then type = $type and code = $code and gender = $gender
else type = $type
end;
Update.
An alternative solution could be to get results in a single json object, what will enable you to use coalesce():
select coalesce(
(select jsonb_agg(to_jsonb(p))
from profile p
where type = $type and code = $code and gender = $gender),
(select jsonb_agg(to_jsonb(p))
from profile p
where type = $type)
);

tell me the sql

I have a table like this.
Table name : message
mid | mfrom | mto | msg
------------------------
1 | a | b | hi
2 | b | a | hello
3 | a | c | how are you
4 | c | a | fine
i am able to show all rows by
`$sql = mysql_query("SELECT *
FROM message
WHERE mto = '$to'
OR mfrom = '$to';");
while($row = mysql_fetch_array($sql))
{
echo $row['msg'];
}`
but i want to show only one result if mfrom and mto or mto and mfrom is equal. Such as if mfrom =a and mto=b or mfrom=b and mto=a. I want to show only one result from them like this
mid | mfrom | mto | msg
-------------------------
2 | b | a | hello
4 | c | a | fine
please tell me the query.
Your question is not clear because your "query" seems wrong ("mfrom and mto or mto and mfrom is equal" doesn't seem correct).
Nevertheless, as you named the table "message", I'm guessing that you want each message once even though it appears twice in the table.
What you could do is query from the table "twice" and then use the bigger of the ids:
SELECT first.* FROM message AS first LEFT JOIN message AS second
ON first.mfrom = second.mto AND first.mto = second.mfrom
WHERE first.mid > second.mid OR second.mid is NULL;
This would give you the result you requested. It would also give you any message that doesn't have a "partner" row.
If you want only matching messages, you can remove the "OR second.mid is NULL".

Postgresql : Alternative to joining the same table multiple times

If i have two tables entry and entry_metadata, with the entry_metadata as a description table for the entry referenced by entry_id and a variable.
If i have this :
entry
id | name |
-------------
1 | entry1 |
2 | entry2 |
3 | entry3 |
entry_metadata
id | entry_id | variable | value
1 | 1 | width | 10
2 | 1 | height | 5
3 | 2 | width | 8
4 | 2 | height | 7
5 | ... | .... | ..
and i'm getting the table :
id | name | width | height| ... | ...
-----------------------------------------
1 | entry1 | 10 | 5 |
2 | entry2 | 8 | 7 |
3 | entry3 | .. | .. |
by the sql :
select e.name, em.width, emr.height
from
public.entry e
left join
public.entry_metadata em
on
em.entry_id = e.id and em.variable = 'width'
left join
public.entry_metadata emr
on
emr.entry_id = e.id and emr.variable = 'height'
The query above works. But as I add more variables to get the values (the entry_metadata table includes a large variety of variables) from the entry metadata. The query gets really really slow. every join I do slows down the execution greatly. Is there a way to get around this?
You can also do this with conditional aggregation:
select id, name,
max(case when variable = 'width' then value end) as width,
max(case when variable = 'height' then value end) as height
from public.entry_metadata em
group by id, name;
Adding additional columns is just adding more aggregation functions.
Just use subselects for this:
SELECT
e.id,
e.name,
(SELECT em.value FROM public.entry_metadata em WHERE em.entry_id = e.id AND em.variable = 'width') AS width,
(SELECT em.value FROM public.entry_metadata em WHERE em.entry_id = e.id AND em.variable = 'height') AS height
FROM
public.entry e
So for each new variable you just need to add one more subselect.
Is there a way to get around this?
Yes, replace entry_metadata table with addtional column in entry (possible solutions are hstore or jsonb) with key - value storage of entry metadata.
Btw. your tables represents well known controversial database desing pattern known as "Entity Attribute Value".

Slick query => duplicated result

I got those models (simplified) :
User(id: Int, name: String)
Restaurant(id: Int, ownerId: Int, name: String)
Employee(userId: Int, restaurantId: Int)
when I use this query :
for {
r <- Restaurants
e <- Employees
if r.ownerId === userId || (e.userId === userId && e.restaurantId === r.id)
} yield r
which is converted to :
select x2."id", x2."owner_id", x2."name" from "restaurants" x2, "employees" x3 where (x2."owner_id" = 2) or ((x3."user_id" = 2) and (x3."restaurant_id" = x2."id"))
So far no problems. But when I insert those data :
User(1, "Foo")
User(2, "Fuu")
Restaurant(1, 2, "Fuu")
Restaurant(2, 1, "Foo")
Restaurant(3, 1, "Bar")
Employee(2, 2)
Employee(2, 3)
then try to query, I get this result :
List(Restaurant(1, 2, "Fuu"), Restaurant(1, 2, "Fuu"), Restaurant(2, 1, "Foo"), Restaurant(3, 1, "Bar))
I do not understand why Restaurant(1, 2, "Fuu") is present 2 times.
(I am using org.h2.Driver with url jdbc:h2:mem:play)
Am I missing something ?
Why you are getting 4 rows back
Cross joins are hard; what you are asking for with your SQL query is:
-- A Cartesian product of all of the rows in restaurants and employees
Employee.user_id | Employee.restaurant_id | Restaurant.name | Restaurant.owner_id
2 | 2 | Fuu | 2
2 | 3 | Fuu | 2
2 | 2 | Foo | 1
2 | 3 | Foo | 1
2 | 2 | Bar | 1
2 | 3 | Bar | 1
-- Filtering out those where the owner != 2
Employee.user_id | Employee.restaurant_id | Restaurant.name | Restaurant.owner_id
2 | 2 | Fuu | 2
2 | 3 | Fuu | 2
-- And combining that set with the set of those where the employee's user_id = 2
-- and the restaurant's ID is equal to the employee's restaurant ID
Employee.user_id | Employee.restaurant_id | Restaurant.name | Restaurant.owner_id
2 | 2 | Foo | 1
2 | 2 | Bar | 1
How to fix it
Make it an explicit left-join instead:
for {
(r, e) <- Restaurants leftJoin Employees on (_.id = _.restaurantId)
if r.ownerId === userId || e.userId === userId
} yield r
Alternately, use exists to make it even clearer:
for {
r <- Restaurants
if r.ownerId === userId ||
Employees.filter(e => e.userId === userId && e.restaurantId === r.id).exists
} yield r

Postgres/Postgis - Querying all values in clipped raster

I'm currently using Postgres 9.1
My goal is to clip a PostGIS raster with a polygon. Then I would like either an postgres array or delimited set of values for each of the raster pixels that are contained within that polygon. Here is the query I have gotten so far:
SELECT p.gid, (ST_ValueCount(ST_Clip(r.rast, p.geom))).value AS fval
FROM temp_raster AS r, temp_shapefile AS p
WHERE (r.start_time = 1384516800)
GROUP BY gid, fval;
This will output:
gid | fcstval
-----+---------
1 | 0
1 | 2
2 | 0
2 | 2
3 | 5
4 | 0
4 | 1
4 | 2
4 | 3
4 | 5
This data is good, but I would like a set of values for each gid like this:
gid | fcstval
-----+----------
1 | 0,2
2 | 0,2
3 | 5
4 | 0,1,2,3,5
The trouble I'm having is trying to then get these values aggregated into either an array or delimited string. Here's my attempt at an array:
SELECT p.gid, array_agg((ST_ValueCount(ST_Clip(r.rast, p.geom))).value) AS fval
FROM temp_raster AS r, temp_shapefile AS p
WHERE (r.start_time = 1384516800)
GROUP BY gid;
This doesn't work, and provides the error:
ERROR: set-valued function called in context that cannot accept a set
My guess is this is because I can't call array_agg in this way. I'm having a bit of difficulty figuring out how to do this otherwise. A subquery perhaps? I haven't been able to come up with anything yet though to get this working.
Thanks for any help!
Okay I think I figured it out for arrays. If I want it in a string, I can just convert my array to a string. However if anyone has any suggestions of cleaning this up I would appreciate it, as this doesn't seem like the simplest markup
SELECT p.gid, array_agg((subquery).tempval) as fcstval
FROM pih_raster AS r, hwy_pih_vertex_buf AS p,
(
SELECT p.gid AS tempgid, (ST_ValueCount(ST_Clip(r.rast, p.geom))).value AS tempval
FROM pih_raster AS r, hwy_pih_vertex_buf AS p
WHERE (r.start_time <= 1384624800) GROUP BY tempgid, tempval
) AS subquery
WHERE (r.start_time <= 1384624800) AND ((subquery).tempgid = gid) GROUP BY p.gid;
Here's the output:
gid | fcstval
-----+-------------
1 | {0,2}
2 | {0,2}
3 | {5}
4 | {0,1,2,3,5}