The nested query does not have the appropriate keys - sql

Firstly I have a function which takes 2 parameters( longitude, latitude).
RETURNS TABLE
AS
RETURN
(
select dbo.GeoCalculateDistance (#lat1Degrees,#lon1Degrees,Latitude,Longitude) as Distance, PKRestaurantId as PkKeyId from StRestaurant
)
And as you realise, I have a table that called StRestaurant. In this table I have 4 columns(PkRestaurantId, RegionId , Longitude, Latitude).
And, I need a method that takes 4 parameters.
public List<RestaurantDetailDto> GetRestaurant(int regionid, decimal latitude, decimal longitude, OrderType orderType)
{}
This method will give the restauants around me. But if I want to systematize this list with distance, I must join my Restaurant table and the function. Here is my query.
var query = from restaurant in context.StRestaurant
join distance in context.CalculateDistanceTable(latitude, longitude) on restaurant.PKRestaurantId equals distance.PkKeyId
where restaurant.FKRegionId == regionid
select new
{
Restaurant = restaurant,
DistanceTable = distance,
};
And then I am checking the orderType,
switch (orderType)
{
case OrderType.Distance:
query = query.OrderBy(x => x.DistanceTable.Distance);
break;
// and the anothers
}
Lastly, I am trying to take this list as;
var queryResult = query.ToList();
All the time I took this error :
The nested query does not have the appropriate keys.
I also try the above query but it return with the same error :s
var query = context.StRestaurant.Where(x => x.FKRegionId == regionid && x.IsActive).Join(
context.CalculateDistanceTable(latitude, longitude),
restaurant => restaurant.PKRestaurantId,
result => result.PkKeyId,
(restaurant, result) => new
{
Restaurant = restaurant,
MinumumPackagePrice = restaurant.StRestaurantRegionRelation.FirstOrDefault(x => x.FKRestaurantId == restaurant.PKRestaurantId).MinumumPackageCharge,
DistanceTable = result,
RestaurantImage = restaurant.StRestaurantImage.Where(x => x.IsDefault && x.FKRestaurantId == restaurant.PKRestaurantId),
}
);
Please help!!

I've seen this before when doing an .Include() on the result. I imagine your projection (in the second example) might be doing this internally. Could you add this to the first part?
In this case, I've had to add the .Include() on the source table:
from a in context.A.Include("relationship")
join b in context.MyFunction(...)
...

There are a some things that you can try here. First, rewrite your SQL function so that it has a primary key:
CREATE FUNCTION CalculateDistanceTable
(
-- Add the parameters for the function here
#lat1Degrees float,
#lon1Degrees float
)
RETURNS
#RestaurantDistances TABLE
(
-- Add the column definitions for the TABLE variable here
PkKeyId int NOT NULL primary key,
Distance float NOT NULL
)
AS
BEGIN
INSERT INTO #RestaurantDistances
SELECT dbo.GeoCalculateDistance(#lat1Degrees, #lon1Degrees, Latitude, Longitude) AS Distance, PKRestaurantId AS PkKeyId
FROM StRestaurant
RETURN
END
GO
Also, you can try changing your LINQ join to use anonymous types to perform the join.
var query = from restaurant in context.StRestaurant
join distance in context.CalculateDistanceTable(latitude, longitude) on new { Key = restaurant.PKRestaurantId } equals new { Key = distance.PkKeyId }
where restaurant.FKRegionId == regionid
select new
{
Restaurant = restaurant,
DistanceTable = distance,
};
If neither one of these helps let me know and I'll try to update this answer as appropriate.

Related

How to combine two SQL queries with dynamic table name into one in PostgreSQL

I have this SQL function which I'm trying to figure out how to make into one query:
async function verifyInteractiveInstanceAttributeIsUnique(typeId, key, val, attrSchema) {
const tableName = getTableName(attrSchema.type)
const instances = await knex.from(`links`)
.select('id')
.where('parent_id', typeId)
.where('name', 'instance')
const instanceIds = instances.map(x => x.id)
const existingRecord = await knex.from(tableName)
.whereIn('parent_id', instanceIds)
.where('name', key)
.first()
return !existingRecord
}
Essentially I think this is the SQL:
SELECT id FROM links
WHERE parent_id = ${typeId}
AND name = 'instance'
# store in IDS array lets say
SELECT * FROM ${tableName}
WHERE parent_id IN (IDS)
AND name = ${key}
LIMIT 1
How can I write this in plain SQL to do the query in one call?
Based on your sample SQL, you can use a subquery:
SELECT t.*
FROM ${tableName} t
WHERE t.parent_id IN (SELECT l.id
FROM links l
WHERE l.parent_id = ${typeId} AND
lname = 'instance'
) AND
t.l.name = ${key}
LIMIT 1

Dynamic column search in multiple tables with gorm golang

My scenario is i have a grid with search option where user can select the column and can do the search, the grid data is coming from various tables. I have attached a sample screen of grid.
User Screen
So i'm trying to create a dynamic query for search but the problem is i can able to search only in main table (schema.Robot) not in Preload tables. whenever i trying to search data data from Preload tables let say from RobotModel table that time getting below error
pq: missing FROM-clause entry for table "robot_models"
Here is my go code
func (r *RobotsRepository) GetRobotsSummary(listParams viewmodel.ListParams, companyID uint) ([]*schema.Robot, int, error) {
mrobots := []*schema.Robot{}
var count int
var order string
if listParams.SortColumn == "" {
listParams.SortColumn = "id"
listParams.SortOrder = 1
} else {
listParams.SortColumn = util.Underscore(listParams.SortColumn)
}
if listParams.SortOrder == 0 {
order = "ASC"
} else {
order = "DESC"
}
var searchQuery string
if listParams.SearchText != "" {
switch listParams.SearchColumn {
case "Robot":
listParams.SearchColumn = "name"
case "Model":
listParams.SearchColumn = "robot_models.name"
}
searchQuery = listParams.SearchColumn +" LIKE '%"+ listParams.SearchText +"%' and Company_ID = " + fmt.Sprint(companyID)
}else{
searchQuery = "Company_ID = " + fmt.Sprint(companyID)
}
orderBy := fmt.Sprintf("%s %s", listParams.SortColumn, order)
err := r.Conn.
Preload("RobotModel", func(db *gorm.DB) *gorm.DB {
return db.Select("ID,Name")
}).
Preload("Task", func(db *gorm.DB) *gorm.DB {
return db.Where("Task_Status in ('In-Progress','Pending')").Select("ID, Task_Status")
}).
Preload("CreatedUser", func(db *gorm.DB) *gorm.DB {
return db.Select("ID,Display_Name")
}).
Preload("UpdatedUser", func(db *gorm.DB) *gorm.DB {
return db.Select("ID,Display_Name")
}).
Where(searchQuery).
Order(orderBy).
Offset(listParams.PageSize * (listParams.PageNo - 1)).
Limit(listParams.PageSize).
Find(&mrobots).Error
r.Conn.Model(&schema.Robot{}).Where(searchQuery).Count(&count)
return mrobots, count, err
}
In searchQuery variable i'm storing my dynamic query.
My question is how can i search data for preload table columns
Here is the sql query which i'm trying to achieve using gorm
SELECT robots.id,robots.name,robot_models.name as
model_name,count(tasks.task_status) as task_on_hand,
robots.updated_at,users.user_name as updated_by
FROM rfm.robots as robots
left join rfm.tasks as tasks on tasks.robot_id = robots.id and
tasks.task_status in ('In-Progress','Pending')
left join rfm.robot_models as robot_models on robot_models.id =
robots.robot_model_id
left join rfm.users as users on users.id = robots.updated_by
WHERE robot_models.name::varchar like '%RNR%' and robots.deleted_at is null
GROUP BY robots.id,robot_models.name,users.user_name
ORDER BY task_on_hand DESC LIMIT 2 OFFSET 0
and sorry for bad English!
Even though you are preloading, you are still required to explicitly use joins when filtering and ordering on columns on other tables. Preloading is used to eagerly load the data to map into your models, not to join tables.
Chain on something like this:
.Joins("LEFT JOIN rfm.robot_models AS robot_models ON robot_models.id = robots.robot_model_id")
I'm not positive if you can use the AS keyword using this technique, but if not, it should be easy enough to adjust your query accordingly.

Convert SQL to LINQ with group by

I'm stumped trying to convert the following sql to linq:
SELECT t.* FROM(SELECT mwfieldid,MAX([TimeStamp]) AS MaxValue, BatchDocumentID
FROM mw_BatchField
GROUP BY mwfieldid,BatchDocumentID) x
JOIN mw_BatchField t ON x.mwfieldid = t.mwfieldid
AND x.MaxValue = t.TimeStamp
and x.BatchDocumentID = t.BatchDocumentID
So far I had to convert it to a stored proc to get it to work. I'd rather know how to write this correctly in linq. I tried using a sql to linq converter (http://www.sqltolinq.com/) which produced this code that had errors in it: (Are these converters any good? It didn't seem to produce anything useful with a few tries.)
From x In (
(From mw_BatchFields In db.mw_BatchFields
Group mw_BatchFields By
mw_BatchFields.MWFieldID,
mw_BatchFields.BatchDocumentID
Into g = Group
Select
MWFieldID,
MaxValue = CType(g.Max(Function(p) p.TimeStamp),DateTime?),
BatchDocumentID)
)
Join t In db.mw_BatchFields
On New With { .MWFieldID = CInt(x.MWFieldID), .MaxValue = CDate(x.MaxValue), .BatchDocumentID = CInt(x.BatchDocumentID) }
Equals New With { .MWFieldID = t.MWFieldID, .MaxValue = t.TimeStamp, .BatchDocumentID = t.BatchDocumentID }
Select
BatchFieldID = t.BatchFieldID,
BatchDocumentID = t.BatchDocumentID,
MWFieldID = t.MWFieldID,
TimeStamp = t.TimeStamp,
value = t.value,
DictionaryValue = t.DictionaryValue,
AutoFilled = t.AutoFilled,
employeeID = t.employeeID
Seems like a lot of code for such a simple query, and it doesn't compile.
So for every combination of mwfieldid and BatchDocumentID you want all columns of the row with the highest TimeStamp? This is something which is much easier to express in LINQ than SQL so I'm not surprised that an automated converter is making a meal of it.
You should be able to do:
Mw_BatchFields.GroupBy(x => new { x.Mwfieldid, x.BatchDocumentId })
.SelectMany(x => x.Where(y => y.TimeStamp == x.Max(z => z.TimeStamp)))
This (like your SQL) will return multiple rows per grouping key if there is more than one row in the group that shares the same maximum TimeStamp. If you only want row per key, you could use:
Mw_BatchFields.GroupBy(x => new { x.Mwfieldid, x.BatchDocumentId })
.Select(x => x.OrderByDescending(y => y.TimeStamp).First())
Edit:
Sorry, just twigged that you're working in VB, not C#, so not quite what you were looking for, but if you can live with the lambda syntax style, I think the above can be translated as:
Mw_BatchFields.GroupBy(Function(x) New With {x.Mwfieldid, x.BatchDocumentId}).Select(Function(x) x.OrderByDescending(Function(y) y.TimeStamp).First())
and:
Mw_BatchFields.GroupBy(Function(x) New With {x.Mwfieldid, x.BatchDocumentId}).SelectMany(Function(x) x.Where(Function(y) y.TimeStamp = x.Max(Function(z) z.TimeStamp)))

Linq query using list output as input

I am using Linqpad and have odata connection setup.
I have a query as follows
QUERY1
void Main()
{var a = from cpuid in Computers
where cpuid.DnsHostName == "xyz"
select new {
ID = cpuid.TechnicalProductsHosted.Select (x => new { Id = x.Id }),
System_Dept = cpuid.SystemDepartment,
};
Console.WriteLine(a);
}
The output : it returns 4 ids but one department which is common among all four id's. When i query otherway round i.e
QUERY2
var a = from id in TechnicalProducts
where id.Id == "ID-15784"
select new
{System_Dept = id.Computers.Select(x => x.SystemDepartment),
Support_Team = id.Computers.Select(x => x.SupportTeam)
};
Console.WriteLine(a);
The output : 4 departments for the id. I wish to have the whole list of departments in the first case. How is it possible? In query 1 Can i take id as input for System Department and query it somehow?
the output samples

Get data from another column where first column id is equals other and other column equals X

My problem is:
I would like to get all advertistments where id of Description column is equals with Advertistment's column.
Let's say that Advertistment column is connected with Description column.
I would like to gain all description's id where one of its column called type_of_house is equals m.
Then show all advertistment where advertistment's id is equals with description's id.
In short way: advertistment shows info about houses, descriptions store houses type D and M and I want show all advertistments with houses type of M.
This is correct sql:
SELECT * FROM advertistment, description WHERE advertistment.id_advertistment = description.id_description AND description.type_of_house = "m"
I have no idea how write it into zend. I tried something like that. This function I wrote in model folder.
public function takeAll() {
$select = $this->_db->select();
$select->from(array('a' => 'advertistment', 'd' => 'description'));
$select->where('a.id_advertistment = d.id_description AND d.type_of_house = m');
return $select->query()->fetchAll();
}
You're actually quite close. This should work:
public function takeAll() {
$select = $this->_db->select();
$select->from(array('a' => 'advertistment'));
$select->join(array('d' => 'description'), 'a.id_advertistment = d.id_description');
$select->where('d.type_of_house = ?', 'm');
return $this->_db->fetchAll($select);
}