how to add a where clause to a query in Power query? - powerquery

I need to return a set of data from a database based on a parameter that is in excel.
So I have created the following 'Query1'
let
Source = Sql.Database("VI107064\SQLEXPRESS", "Stock", [Query="select * from customer#(lf)where custID = " &CustID])
in
Source
Then I created the 'CustID'
let
Source = Excel.CurrentWorkbook(){[Name="CustID"]}[Content],
SourceValue = Record.Field(Source{0}, "CustID"),
SourceText = Number.ToText(SourceValue)
in
SourceText
The issue is that Excel is complaining that the query refernces other queries or steps, so it may not directly access a datasource Please rebuild this data combination.
So after reading https://www.excelguru.ca/blog/2015/03/11/power-query-errors-please-rebuild-this-data-combination/
I understood the issue, and I think for me to fix the problem, I need to duplicate query1 to query2.
Update query 1 so that it just returns the table.
Update query 2 so that it takes query 1 as a source and then adds the filter.
Is that correct? or is there a better way to do this?

The simplest solution, if you aren't worried about data privacy settings, is to turn those settings off.
File > Options and settings > Query Options > Privacy
In any case, I'd recommend cleaning up the code to be a single query that looks something like this:
let
CustID = Excel.CurrentWorkbook(){[Name="CustID"]}[Content]{0}[Column1],
Source = Sql.Database("VI107064\SQLEXPRESS", "Stock"){[Schema="dbo",Item="customer"]}[Data],
#"Filtered Rows" = Table.SelectRows(Source, each ([CustID] = CustID))
in
#"Filtered Rows"
If you right-click on the last step in the Applied Steps pane, you can see that this get interpreted in the SQL Native Query as
select [_].[ <A bunch of columns here> ],
[_].[ <...> ],
[_].[ <etc> ]
from [dbo].[customer] as [_]
where [_].[CustID] = <CustID value here>

Related

using :APP_USER in a query in apex application

I have a query in my apex page and I want to see the result of this query in the page:
select locs.LOCATION_DESCRIPTION "LOCATION", rsrv.Room_ID "Room Number",
rsrv.WORKPLACE_ID "Desk Number", rsrv.RESERVATION_DATE "Date", rsrv.TIME_FROM
"From", rsrv.TIME_TO "To"
FROM WPB_RESERVATIONS rsrv, WPB_USERNAMES usrs, WPB_LOCATIONS locs
WHERE upper(usrs.APEX_USERNAME) = upper(:APP_USER)
AND (upper(rsrv.FIRST_NAME) = upper(usrs.FIRST_NAME) AND upper(rsrv.LAST_NAME) =
upper(usrs.LAST_NAME))
AND rsrv.LOC_ID = locs.LOC_ID
AND rsrv.RESERVATION_DATE >= SYSDATE-1
but it shows nothing. IT seems this part doesnt work:
WHERE upper(usrs.APEX_USERNAME) = upper(:APP_USER)
because when I change it to this I can see the results that I want:
WHERE upper(usrs.APEX_USERNAME) = 'MS'
I've read all topics about using :APP_USER or v(APP_USER) and tried different solutions, but non of them works.
Well, if it works when you hardcode 'MS' and it does not work when you do UPPER(:APP_USER) that indicates that those 2 values are not the same. You have not mentioned what the value for the APP_USER is. Best way to check is to open the session state window from the developer toolbar and check what the value for "User" is.
If you're still working on this, my suggestion would be to temporarily:
Hardcode the 'MS' into the WHERE clause (or drop that comparison entirely,
Add a dummy column to your query with this as the source
upper(:APP_USER) AS the_app_user
That will let you see the application item value in the report results.

How to skip update when parameter is null/0 in spring batch with JdbcBatchItemWriter

We have a scenario wherein while doing a batch update on a table using JdbcBatchItemWriter, We are not finding a way to not update is the attribute is null. We don't want to have too many queries and ItemPreparedStatementSetter so we have a single query to update all fields in the table. Different batch jobs set update different attributes of the table
List<Report> summaryList = getSummaryList()
JdbcBatchItemWriter<ItemMktDcGpReport> writer1 = new JdbcBatchItemWriter<>();
String sql_update = GenericConstants.UPDATE_QUERY;
writer1.setDataSource(dataSource);
ItemPreparedStatementSetter<Report> updatePreparedStatementSetter = new ItemMergeUpdatePreparedItemSetter();
writer1.setItemPreparedStatementSetter(updatePreparedStatementSetter);
writer1.setSql(sql_update);
writer1.afterPropertiesSet();
writer1.write(summaryList);
Tried the following seeing few examples on conditional update at the query but it doesn't help yet.
Below is the query. Any help on this will be very much appreciated.
UPDATE_QUERY = "update [dbo].[test_tbl]
SET test_col1 = CASE When ?!=0 then ?
else test_col1 end ,
test_col2 = CASE When ?!=0 then ?
else test_col2 WHERE market=? and country = ?"
I don't want to construct the SQL query based on parameter as I will lose out on the bulk writing feature of JdbcBatchItemWriter. Can someone please suggest the right approach to solve this problem and possibly correct the SQL query I'm writing?

How to add a parameter to a SQL query?

I would like to add a dynamic parameter in addition to parameters from Maximo inside SQL query.
Something like that :
select *
from workorder a
where params["where"] or a.parent = :Param
with params["where"] with wonum='1234' and :Param = '1234'
Is it possible with Birt to get wonum value and put it also to :Param ?
Or maybe another way ?
Thanks
open is like that (query is more complicated so I simplify it):
maximoDataSet = MXReportDataSetProvider.create(this.getDataSource().getName(), this.getName());
maximoDataSet.open();
var sqlText = new String();
sqlText = "select column1, column2 as woParent, etc... from workorder where " + params["where"] + " or woParent=:param";
maximoDataSet.setQuery(sqlText);
beforeopen is like that(just to see the query) :
importPackage( Packages.java.io );
out = new PrintWriter( new FileWriter( "c:/birteaump.log", true ) );
out.println( "\nMy Query: " + this.queryText);
out.close();
I had some code to manipulate :param to replace it with wonum but this.queryText is null.
I'm a newbie to birt report maybe I have to think differently to solve my problem.
Thanks
I used Birt 3.7.1. I saw in a video that we can add a query in a dataset's dialog box. But with my report I only have "scripted data set" when I use the "new data set" button.
Is it possible that my query is null in "beforeopen" is in relation with that ?
If I create another sort of datasource, I will have acces to another sort of dataset ?
thanks
ok I solved my problem.
I created a JDBC data source and I have access to a new sort of data set.
I can put my query in this data set and I have access to "beforeopen" and my query is not null.
Thanks

Linq to Entities - Filter on any item in one list belonging to another list

Here is my scenario. I have a Document class. The document is associated with a DocumentClasses table through a many to many relationship, so a document can have one or more classes. When running a search, the user can choose to filter documents by class. So, I need to be able to append a where clause to my query if the user chooses to select any classes. The logic is that if the document is assigned to any of the classes in the classes the user selected, the document should be returned. So the basic query needed in pseudo code. So basically, if any number in list A belongs to list B, then return the record.
I have tried this (RestrictByClasses is just a List(Of Integer)):
query = query.where(Function(resultItem) RestrictByClasses.Contains(resultItem.DocumentClassIds.Any())
But I get the following exception:
The nested query is not supported. Operation1='Case' Operation2='Collect'
Is there any way to get linq to filter records out like this?
Thanks!
UPDATE:
After doing a little more debugging, I think that it is more to do with how I am projecting onto the object in order to load it with values that can be used to filter. Here is how I am doing the projection:
Dim query = From document In dbContext.Documents
Select New FeeAndReceptionReportIntermediateItem With
{
.BookTypeId = If(restrictByBookTypes AndAlso document.DocumentInstruments.Any(), document.DocumentInstruments.FirstOrDefault().Instrument.BookTypeId, Nothing),
.CustomerId = document.CustomerId,
.DocumentClassIds = If(restrictByDocumentClasses, document.DocumentClasses.Select(Function(group) group.ClassId), Nothing),
.DocumentId = document.DocumentId,
.DocumentNumber = document.DocumentNumber,
.DepartmentId = document.DepartmentId,
.InstrumentGroupIds = If(restrictByInstrumentGroup, document.DocumentInstruments.FirstOrDefault().Instrument.InstrumentGroups.Select(Function(group) group.InstrumentGroupId), Nothing),
.RecordDateTime = document.RecordDateTime,
.RestrictedInstrument = (includeRestrictedDocuments AndAlso document.DocumentInstruments.Any() AndAlso document.DocumentInstruments.FirstOrDefault().Instrument.Restricted)
}
I think it is complaining about how the .DocumentClassIds and .InstrumentGroupId's are being loaded into the POCO object (FeeAndReceptionReportIntermediateItem). I would really like to load these up in the initial query, before a .ToList() has been called and I would really like to not even do the join if the user did not pass in the restrictions that require me to create the join, that's why I am using the navigation properties and an if statement when loading these collecctions, because I am assuming if "restrictByDocumentClasses" is false, the navigation property won't be accessed and the join won't be included.
This works as a general pattern. The first line gets an IQueryable<> from the DbSet<>. The select does this for us, so that we can continue reusing query to hold our query as we build it up. Then just keep adding on If...Then...query=query.Where(...)...Endif to continue whittling down the resultset.
var query=db.MyTable.Select(x=>x);
if (RestrictByClasses.Any())
query=query.Where(r =>
r.DocumentClasses.Select(x=>x.ClassId)
.Intersect(RestrictByClasses)
.Any());
if (RestrictBySomethingElse)
query=query.Where(x=>SomethingElse)
I think this is the equivalent in VB.NET:
Dim query = db.MyTable.[Select](Function(x) x)
If RestrictByClasses.Any() Then
query = query.Where(Function(r) r.DocumentClasses.Select(Function(group) group.ClassId).Intersect(RestrictByClasses).Any())
End If
'Repeat as necessary
If RestrictBySomethingElse Then
query = query.Where(Function(x) SomethingElse)
End If
'End repeat
' Rest here is pseudo code
' Sort
SELECT/SWITCH sortonfield
CASE 'name': query=query.OrderBy(Function(x) x.name)
CASE 'dob': query=query.OrderBy(Function(x) x.dob)
DEFAULT: query=query.OrderBy(Function(x) x.id)
END CASE
'Paginate
query=query.Skip((pagenumber-1)*pagesize).Take(pagesize)
'Project
Dim finalresult=query.Select(Function(x) new something {
name=x.Name,
id=x.id,
things=x.things
});
Once all your filters have been put in place (and optionally a sort, and pagination), then project your resultset into whatever you need.

Linq Contains issue: cannot formulate the equivalent of 'WHERE IN' query

In the table ReservationWorkerPeriods there are records of all workers that are planned to work on a given period on any possible machine.
The additional table WorkerOnMachineOnConstructionSite contains columns workerId, MachineId and ConstructionSiteId.
From the table ReservationWorkerPeriods I would like to retrieve just workers who work on selected machine.
In order to retrieve just relevant records from WorkerOnMachineOnConstructionSite table I have written the following code:
var relevantWorkerOnMachineOnConstructionSite = (from cswm in currentConstructionSiteSchedule.ContrustionSiteWorkerOnMachine
where cswm.MachineId == machineId
select cswm).ToList();
workerOnMachineOnConstructionSite = relevantWorkerOnMachineOnConstructionSite as List<ContrustionSiteWorkerOnMachine>;
These records are also used in the application so I don't want to bypass the above code even if is possible to directly retrieve just workerPeriods for workers who work on selected machine. Anyway I haven't figured out how it is possible to retrieve the relevant workerPeriods once we know which userIDs are relevant.
I have tried the following code:
var userIDs = from w in workerOnMachineOnConstructionSite select new {w.WorkerId};
List<ReservationWorkerPeriods> workerPeriods = currentConstructionSiteSchedule.ReservationWorkerPeriods.ToList();
allocatedWorkers = workerPeriods.Where(wp => userIDs.Contains(wp.WorkerId));
but it seems to be incorrect and don't know how to fix it. Does anyone know what is the problem and how it is possible to retrieve just records which contain userIDs from the list?
Currently, you are constructing an anonymous object on the fly, with one property. You'll want to grab the id directly with (note the missing curly braces):
var userIDs = from w in workerOnMachineOnConstructionSite select w.WorkerId;
Also, in such cases, don't call ToList on it - the variable userIDs just contains the query, not the result. If you use that variable in a further query, the provider can translate it to a single sql query.

Resources