SQL Query in Sequelize getter method - node.js

I'm using the Postgres extension 'earthdistance' for lat/long distance calculation.
I'm also using Sequelize to access the database and I want to define a getter
method for calculation and sorting by distance from a set of coordinates.
The following query works fine:
SELECT name,
earth_distance(ll_to_earth( 51.5241182, -0.0758046 ),
ll_to_earth(latitude, longitude)) as distance_from_current_location
FROM "Branches"
ORDER BY distance_from_current_location ASC;
And I can use it using sequelize.query(), but I want to keep all the model queries part of the model.
How can I specify WHERE conditions from inside a getter method in the model definition?
Thanks!

Your best bet is probably to wrap the query in a stored procedure and pass in the arguments you want to use in the where clause. As stored procedures are compiled, this will perform better than a Dynamic SQL where you generate the WHERE clause on the fly.
Add whatever parameters and types to your stored proc as you need, and the result will look something like this:
CREATE FUNCTION GetEarthDistance (v_Foo bigint) RETURNS type AS $$
DECLARE
v_Name varchar(256);
BEGIN
SELECT name INTO v_Name,
earth_distance(ll_to_earth( 51.5241182, -0.0758046 ),
ll_to_earth(latitude, longitude)) as distance_from_current_location
FROM Branches
WHERE somecol > v_foo
ORDER BY distance_from_current_location ASC;
RETURN v_Name;
END;
$$ LANGUAGE 'plpgsql';

Related

How to add a where clause to Sequelize functions?

I'm trying to use aggregate functions to extract multiple different sums from a table using multiple different where clauses.
I'm trying to do something like this:
model.findAll({
attributes:[
[sequelize.fn('sum', sequelize.col('columnA')), 'sumA1'], // need to add where:{condition1}
[sequelize.fn('sum', sequelize.col('columnB')), 'sumB1'], // need to add where:{condition1}
[sequelize.fn('sum', sequelize.col('columnA')), 'sumA2'], // need to add where:{condition2}
[sequelize.fn('sum', sequelize.col('columnB')), 'sumB2'], // need to add where:{condition2}
...
]
)}
So far I've managed to make this work using Promise.all and making different calls to the database for each "where clause condition" or getting all data from the table and using node to calculate the sums. Is there a better way of doing this using sequelize?
If you prefer the literal way then it would be simple with subquery where
model.findAll({
limit: 1,
attributes:[
[sequelize.literal(`(select sum(columnA) from table where date = '2021-01-05')`), 'testSum'],
...and so on
]
})
you see from basic SQL concept the thing you need to perform is subquery or the over() clause using the window in either cases you need have a raw query first and then try to convert it over to sequelize syntax.

Kusto Usecases (Nested User Defined Functions)

Could you please let me know if the following usecases can be handled in Kusto?
Nested User defined queries (Can I call one function in the other function)?Here are the two functions
.create function ifnotexists
with()
function1() {table1 | where column1 == abs}
.create function ifnotexists
with()
function2() {table2 | where column1 in (function1())}
Also How to add row level security policy to the nested function - function2()?The below does not seem to work
.alter table table2 policy row_level_security enable "function2"
2.How do I Upsert a row (Can I create a new table and migrate the schema). If so, Is it possible to make users have access to just the functions and not the underlying tables??
Note: I can write a function to point to a new table with upserted row
It is possible to use other functions inside a function. Nothing special - your example should work.
Migrating table can be done with .set-or-append command:
https://learn.microsoft.com/en-us/azure/data-explorer/kusto/management/data-ingestion/ingest-from-query
It is not possible to let user access functions only. Some scenarios of user-restriction can be solved with Row-level-security: https://learn.microsoft.com/en-us/azure/data-explorer/kusto/management/rowlevelsecuritypolicy
Some scenarios of "changing" rows can be done with "summarize arg_max(Time, *)" clause - where Time is the time of the update.
https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/arg-max-aggfunction

Is there any alternative of CREATE TYPE in SQL as CREATE TYPE is Not supported in Azure SQL data warehouse

I am trying to execute this query but as userdefined(Create type) types are not supportable in azure data warehouse. and i want to use it in stored procedure.
CREATE TYPE DataTypeforCustomerTable AS TABLE(
PersonID int,
Name varchar(255),
LastModifytime datetime
);
GO
CREATE PROCEDURE usp_upsert_customer_table #customer_table DataTypeforCustomerTable READONLY
AS
BEGIN
MERGE customer_table AS target
USING #customer_table AS source
ON (target.PersonID = source.PersonID)
WHEN MATCHED THEN
UPDATE SET Name = source.Name,LastModifytime = source.LastModifytime
WHEN NOT MATCHED THEN
INSERT (PersonID, Name, LastModifytime)
VALUES (source.PersonID, source.Name, source.LastModifytime);
END
GO
CREATE TYPE DataTypeforProjectTable AS TABLE(
Project varchar(255),
Creationtime datetime
);
GO
CREATE PROCEDURE usp_upsert_project_table #project_table DataTypeforProjectTable READONLY
AS
BEGIN
MERGE project_table AS target
USING #project_table AS source
ON (target.Project = source.Project)
WHEN MATCHED THEN
UPDATE SET Creationtime = source.Creationtime
WHEN NOT MATCHED THEN
INSERT (Project, Creationtime)
VALUES (source.Project, source.Creationtime);
END
Is there any alternative way to do this.
You've got a few challenges there, because most of what you're trying to convert is not the way to do things on ASDW.
First, as you point out, CREATE TYPE is not supported, and there is no equivalent alternative.
Next, the code appears to be doing single inserts to a table. That's really bad on ASDW, performance will be dreadful.
Next, there's no MERGE statement (yet) for ASDW. That's because UPDATE is not the best way to handle changing data.
And last, stored procedures work a little differently on ASDW, they're not compiled, but interpreted each time the procedure is called. Stored procedures are great for big chunks of table-level logic, but not recommended for high volume calls with single-row operations.
I'd need to know more about the use case to make specific recommendations, but in general you need to think in tables rather than rows. In particular, focus on the CREATE TABLE AS (CTAS) way of handling your ELT.
Here's a good link, it shows how the equivalent of a Merge/Upsert can be handled using a CTAS:
https://learn.microsoft.com/en-us/azure/sql-data-warehouse/sql-data-warehouse-develop-ctas#replace-merge-statements
As you'll see, it processes two tables at a time, rather than one row. This means you'll need to review the logic that called your stored procedure example.
If you get your head around doing everything in CTAS, and separately around Distribution, you're well on your way to having a high performance data warehouse.
Temp tables in Azure SQL Data Warehouse have a slightly different behaviour to box product SQL Server or Azure SQL Database - they exist at the session level. So all you have to do is convert your CREATE TYPE statements to temp tables and split the MERGE out into separate INSERT / UPDATE / DELETE statements as required.
Example:
CREATE TABLE #DataTypeforCustomerTable (
PersonID INT,
Name VARCHAR(255),
LastModifytime DATETIME
)
WITH
(
DISTRIBUTION = HASH( PersonID ),
HEAP
)
GO
CREATE PROCEDURE usp_upsert_customer_table
AS
BEGIN
-- Add records which do not already exist
INSERT INTO customer_table ( PersonID, Name, LastModifytime )
SELECT PersonID, Name, LastModifytime
FROM #DataTypeforCustomerTable AS source
WHERE NOT EXISTS
(
SELECT *
FROM customer_table target
WHERE source.PersonID = target.PersonID
)
...
Simply load the temp table and execute the stored proc. See here for more details on temp table scope.
If you are altering a large portion of the table then you should consider the CTAS approach to create a new table, then rename it as suggested by Ron.

Why can I not use alias name for FUNC in JPQL

I have a JPQL Query something like
select col1,col2, FUNC('CONCAT',FUNC('CONCAT',col3,'-'), col4) as aliascolName.
I need to provide an alias name for my FUNC call as I need to use this concatenated result for providing filtering option from UI and also in ORDER BY Clause.
I am using JPA2.0 with TOPLINK12.1.2

Select only one row in dql subquery

I have to execute following query:
create dm_myobject object
set my_id_attribute = (select r_object_id from dm_otherobject where <some clause here>)
where ...
But subquery in brackets returns more than one id. I can't make whereclause more detailed to retrieve only one value.
How to take first?
ENABLE(FETCH_ALL_RESULTS 1) or ENABLE(RETURN_TOP 1) doesn't help.
In my experience it is impossible to use DQL hints in a sub query like you suggested, because the hint is applied to the query as a whole. It is indeed possible to use, say, ENABLE(RETURN_TOP 1) on a query that contains a sub query, however that hint will then be used on the outer query and never on the inner one. In your case, however, you'll end up with an error message telling that the sub query returns more than one result.
Try using an aggregate function on the selected attribute instead:
CREATE dm_myobject OBJECT
SET my_id_attribute = (
SELECT MIN(r_object_id)
FROM dm_otherobject
WHERE <some clause>
)
The MIN and MAX functions work with ints and strings, and I suspect they work with IDs too. Since it is ok for you to set only the first ID that's returned from your sub query, I suspect you're returning them in a sorted order and want to use the first -- hence the usage of the MIN function.
An alternative approach would of course be to write a script or a small Java program that executes several DQL statements, but that might or might not work for you in your case.

Resources