MVC SQL invalid - asp.net-mvc-4

I have the following code in my MVC Index function. It is called from a search page that allows the user to search for various string values:
public ViewResult Index(string sortOrder, string YearString,string MonthString,string BudgetTypeString,string DescriptionString)
{
ViewBag.BudgetTypeSortParm = String.IsNullOrEmpty(sortOrder) ? "BudgetType_desc" : "";
ViewBag.MonthSortParm = sortOrder == "Date" ? "Month_desc" : "Month";
ViewBag.YearSortParm = sortOrder == "Date" ? "Year_desc" : "Year"; // 12-24-2014 JR added
ViewBag.DescriptionSortParm = sortOrder == "Description" ? "Description_desc" : "Description";
var budg = from s in db.budgets
select s;
if (!String.IsNullOrEmpty(YearString) ||
!String.IsNullOrEmpty(MonthString) ||
!String.IsNullOrEmpty(BudgetTypeString) ||
!String.IsNullOrEmpty(DescriptionString))
{
budg = budg.Where(s => s.BudgetType.ToUpper().Contains(BudgetTypeString.ToUpper()) ||
String.IsNullOrEmpty(BudgetTypeString) || s.Description.ToUpper().Contains(DescriptionString.ToUpper()) ||
String.IsNullOrEmpty(DescriptionString) ||
s.Month.ToUpper().Contains(MonthString.ToUpper()) ||
String.IsNullOrEmpty(MonthString) ||
s.Year.ToUpper().Contains(YearString.ToUpper()) ||
String.IsNullOrEmpty(YearString));
budg = budg.OrderBy(s => s.BudgetType);
return View(db.budgets.ToList());
}
}
Here is the actual SQL that is converted from the above code:
budg {SELECT
[Extent1].[id] AS [id],
[Extent1].[BudgetType] AS [BudgetType],
[Extent1].[Description] AS [Description],
[Extent1].[Amount] AS [Amount],
[Extent1].[Month] AS [Month],
[Extent1].[Year] AS [Year],
[Extent1].[DateStamp] AS [DateStamp]
FROM [dbo].[budget] AS [Extent1]
WHERE (( CAST(CHARINDEX(UPPER(#p__linq__0),
UPPER([Extent1].[BudgetType])) AS int)) > 0) OR
(( CAST(CHARINDEX(UPPER(#p__linq__1), UPPER([Extent1].[Description])) AS int)) > 0) OR
(( CAST(CHARINDEX(UPPER(#p__linq__2), UPPER([Extent1].[Month])) AS int)) > 0) OR
(( CAST(CHARINDEX(UPPER(#p__linq__3), UPPER([Extent1].[Year])) AS int)) > 0)}
Does anyone know why my strings are incorrectly being converted into integers and how to correct it so the search strings on my search page work correctly?

Let's take a look at just one of the Cast statements:
( CAST(CHARINDEX(UPPER(#p__linq__1), UPPER([Extent1].[Description])) AS int)) > 0)
Take a look at the inner statement. It's actually getting the CharIndex of one string in the other. Basically, does "Description" contain #p__linq__1. CharIndex returns 0 if if the first expression is not found in the other. The result of CharIndex is what is being Cast as int, and then compared to see if it is greater than 0. Which is exactly what you asked it to do when you use .Contains

Related

Expanding a Struct of Struct to columns in bigquery

I am working with a BQ table that has a format of a STRUCT of STRUCTs.
It looks as follows:
I would like to have a table which looks like follows:
property_hs_email_last_click_date_value
currentlyinworkflow_value
hs_first_engagement_object_id_value
hs_first_engagement_object_id_value__st
5/5/2022 23:00:00
Y
1
'Hey'
The challenge is that there are 500 fields and I would like to make this efficient instead of writing out every single line as follows:
SELECT property_hs_email_last_click_date as property_hs_email_last_click_date_value,
properties.currentlyinworkflow.value as currentlyinworkflow_value,
properties.hs_first_engagement_object_id.value as properties.hs_first_engagement_object_id_value,
properties.hs_first_engagement_object_id.value__st as hs_first_engagement_object_id_value__st
Any suggestions on how to make this more efficient?
Edit:
Here's a query that creates a table such as this:
create or replace table `project.database.TestTable` (
property_hs_email_last_click_date STRUCT < value string >,
properties struct < currentlyinworkflow struct < value string > ,
hs_first_engagement_object_id struct < value numeric , value__st string >,
first_conversion_event_name struct < value string >
>
);
insert into `project.database.TestTable`
values (struct('12/2/2022 23:00:02'), struct(struct('Yes'), struct(1, 'Thursday'), struct('Festival')) );
insert into `project.database.TestTable`
values (struct('14/2/2021 12:00:02'), struct(struct('No'), struct(5, 'Friday'), struct('Phone')) )
Below is quite generic script that extracts all leaves in JSON and then presents them as columns
create temp function extract_keys(input string) returns array<string> language js as """
return Object.keys(JSON.parse(input));
""";
create temp function extract_values(input string) returns array<string> language js as """
return Object.values(JSON.parse(input));
""";
create temp function extract_all_leaves(input string) returns string language js as '''
function flattenObj(obj, parent = '', res = {}){
for(let key in obj){
let propName = parent ? parent + '.' + key : key;
if(typeof obj[key] == 'object'){
flattenObj(obj[key], propName, res);
} else {
res[propName] = obj[key];
}
}
return JSON.stringify(res);
}
return flattenObj(JSON.parse(input));
''';
create temp table temp_table as (
select offset, key, value, format('%t', t) row_id
from your_table t,
unnest([struct(to_json_string(t) as json)]),
unnest([struct(extract_all_leaves(json) as leaves)]),
unnest(extract_keys(leaves)) key with offset
join unnest(extract_values(leaves)) value with offset
using(offset)
);
execute immediate (select '''
select * except(row_id) from (select * except(offset) from temp_table)
pivot (any_value(value) for replace(key, '.', '__') in (''' || keys_list || '''
))'''
from (select string_agg('"' || replace(key, '.', '__') || '"', ',' order by offset) keys_list from (
select key, min(offset) as offset from temp_table group by key
))
);
if applied to sample data in your question
create temp table your_table as (
select struct('12/2/2022 23:00:02' as value) as property_hs_email_last_click_date ,
struct(
struct('Yes' as value) as currentlyinworkflow ,
struct(1 as value, 'Thursday' as value__st) as hs_first_engagement_object_id ,
struct('Festival' as value) as first_conversion_event_name
) as properties
union all
select struct('14/2/2021 12:00:02'), struct(struct('No'), struct(5, 'Friday'), struct('Phone'))
);
the output is

LINQ Query to search for users with partial name

I have this SQL query:
SELECT
*
FROM
employeeTable
WHERE
(
concat(first_name, ' ', last_name) like concat('%', replace(#MatchString, ' ', '%'), '%')
or
concat(last_name, ' ', first_name) like concat('%', replace(#MatchString, ' ', '%'), '%')
)
It works perfectly by searching both name and last name with partial values., by searching users with partial strings. So for example:
"ric jon" will find Rick Jones, Richard Jonesy, and Jonathan Prichter.
I have the following Linq Query, using Entity Framework:
from employee in context.Employee
where employee.first_name.Contains(matchString)
|| employee.last_name.Contains(matchString)
select employee
But the string "ric jon" does not find anything.
I can't seem to make that linq query work the same as the SQL query.
That SQL wouldn't in fact find those records you sampled with the given "ric jon". What you are asking for is a special filter which IMHO requires a function that is not natively supported by the backend (you didn't specify your backend but anyway at least I don't know a backend that would support this natively). Something like this would work (note that you are getting the Employee records to local, this is not done at backend level):
Func<Employee, string[], bool> match = (emp, _parts) => {
return
((emp.FirstName.IndexOf(_parts[0],StringComparison.CurrentCultureIgnoreCase ) != -1) &&
(_parts.Length == 1 || emp.LastName.IndexOf(_parts[1], StringComparison.CurrentCultureIgnoreCase) != -1)) ||
((_parts.Length == 1 || emp.FirstName.IndexOf(_parts[1], StringComparison.CurrentCultureIgnoreCase) != -1) &&
(emp.LastName.IndexOf(_parts[0], StringComparison.CurrentCultureIgnoreCase) != -1));
};
string search = "ric jon";
var result = context.Employee.AsEnumerable()
.Where(n => match(n, search.Split()));
Update:
You can use this one which would be supported by many backends:
string search = "ric jon";
string[] parts = search.ToLowerInvariant().Split();
string p1 = parts.Length < 1 ? "" :parts[0];
string p2 = parts.Length < 2 ? "" :parts[1];
var result = context.Employee.Where(n =>
((n.FirstName.ToLowerInvariant().Contains(p1) &&
n.LastName.ToLowerInvariant().Contains(p2))) ||
((n.FirstName.ToLowerInvariant().Contains(p2) &&
n.LastName.ToLowerInvariant().Contains(p1))));

Conditional statements in PIG

I have below input in a text file and need to generate output in another file based on the logic.
Here is my input file:
customerid|Dateofsubscription|Customercode|CustomerType|CustomerText
1001|2017-05-23|455|CODE|SPRINT56
1001|2017-05-23|455|DESC|Unlimited Plan
1001|2017-05-23|455|DATE|2017-05-05
1002|2017-05-24|455|CODE|SPRINT56
1002|2017-05-24|455|DESC|Unlimited Plan
1002|2017-05-24|455|DATE|2017-05-06
Logic:
If Customercode = 455
if( CustomerType = "CODE" )
Val= CustomerText
if( CustomerType = "DESC" )
Description = CustomerText
if( CustomerType = "DATE" )
Date = CustomerText
Output:
customerid|Val|Description|Date
1001|SPRINT56|Unlimited Plan|2017-05-05
1002|SPRINT56|Unlimited Plan|2017-05-06
Could you please help me with this.
rawData = LOAD data;
filteredData = FILTER rawData BY (Customercode == 455);
--Extract and set Val/Description/Date based on CustomerText and 'null' otherwise
ExtractedData = FOREACH filteredData GENERATE
customerId,
(CustomerType == "CODE" ? CustomerText : null) AS Val,
(CustomerType == "DESC" ? CustomerText : null) AS Description,
(CustomerType == "DATE" ? CustomerText : null) AS Date;
groupedData = GROUP ExtractedData BY customerId;
--While taking MAX, all 'nulls' will be ignored
finalData = FOREACH groupedData GENERATE
group as CustomerId,
MAX($1.Val) AS Val,
MAX($1.Description) AS Description,
MAX($1.Date) AS Date;
DUMP finalData;
I have specified the core logic. Loading, formatting and storage should be straight-forward.
Filter the input where customercode=455,generate the required 2 columns,then group by customerid and then use BagToString
.
B = FILTER A BY Customercode == 455;
C = FOREACH B GENERATE $0 as CustomerId,$4 as CustomerText;
D = GROUP C BY CustomerId;
E = FOREACH D GENERATE group AS CustomerId, BagToString(C.CustomerText, '|'); -- Note:This will generate 1001,SPRINT56|Unlimited Plan|2017-05-05 so,you will have to concat the first field with '|' and then concat the resulting field with the second field which is already delimited by '|'.
F = FOREACH E GENERATE CONCAT(CONCAT($0,'|'),$1);
DUMP F;

Output a comma separated list in T-SQL

I have a table with phone numbers in it. Instead of spitting out a single row for each number I want to return a comma separated list of phone numbers. What's the easiest way to do this in sql? A while loop?
Some of those answers are overly complicated with coalesce and more complex XML queries. I use this all the time:
select #Phones=(
Select PhoneColumn+','
From TableName
For XML Path(''))
-- Remove trailing comma if necessary
select #Phones=left(#Phones,len(#Phones)-1)
You could create a UDF that would do something like this
CREATE FUNCTION dbo.GetBirthdays(#UserId INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #combined VARCHAR(MAX)
SELECT #combined = COALESCE(#combined + ', ' + colName + ', colName)
FROM YourTable
WHERE UserId = #UserId
ORDER BY ColName
END
Basically this just pulls all of the values into a simple list.
FWIW I created a SQL CLR Aggregate function. Works like a champ!
[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined,
Name = "JoinStrings",
IsInvariantToNulls=true,
IsInvariantToDuplicates=false,
IsInvariantToOrder=false,
MaxByteSize=8000)] public struct
JoinStrings : IBinarySerialize {
public string Result;
public void Init()
{
Result = "";
}
public void Accumulate(SqlString value)
{
if (value.IsNull)
return;
Result += value.Value + ",";
}
public void Merge(JoinStrings Group)
{
Result += Group.Result;
}
public SqlString Terminate()
{
return new SqlString(Result.ToString().Trim(new
char[] { ',' }));
}
public void Read(System.IO.BinaryReader r)
{
Result = r.ReadString();
}
public void Write(System.IO.BinaryWriter w)
{
w.Write(Result.ToString());
} }
I can then use it like this:
SELECT dbo.JoinStrings(Phone) FROM Phones Where UserID = XXX
See my answer from this question. There are a couple of other ways to do it listed in that question also. COALESCE or for xml path should do the trick though.
Edit (added my answer from the previous question):
CREATE FUNCTION [dbo].[fn_MyFunction]()RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE #str NVARCHAR(MAX)
DECLARE #Delimiter CHAR(2)
SET #Delimiter = ', '
SELECT #str = COALESCE(#str + #Delimiter,'') + AColumn
FROM dbo.myTable
RETURN RTRIM(LTRIM(#str))
END
Assuming you have a Customers table which has a unique ID and another table named PhoneNumbers with multiple phone numbers for each customer sharing the Customer ID field as a Foreign Key this would work using a correlated sub-Query
Select C.ID, C.FirstName, C.LastName,
(select (STUFF(( SELECT ', ' + PhoneNumber from PhoneNumbers P where P.CID = C.ID
FOR XML PATH('')), 1, 2, ''))) as PhoneNumbers
from Customers C
Select Unique ID, Replace(Rtrim(Ltrim(Case when [Phone_Number1] is not null Then [Phone_Number1]+' ' Else '' End +
Case when [Phone_Number2] is not null Then [Phone_Number2]+' ' Else '' End +
Case when [Phone_Number3] is not null Then [Phone_Number3]+' ' Else '' End)),' ',', ') as Phone_numbers
From MYTable
Hope this is what you are looking for and I dont know if this will help you so far after the question.

How to Check for the nullable dates in the linq query

I have a array of an object of type employee,
var s = from x in employee
where !string.IsNullOrEmpty(x.FirstName) && (x.FirstName.IndexOf(searchText, StringComparison.OrdinalIgnoreCase)) >= 0 || !string.IsNullOrEmpty(x.LastName) && (x.LastName.IndexOf(searchText, StringComparison.OrdinalIgnoreCase)) >= 0 ||
//I want to check here for null DateOfBirth
x.DateOfBirth.Value.ToShortDateString().StartsWith(searchText, StringComparison.OrdinalIgnoreCase)
select x;
I think all you need is
&& x.DateOfBirth.HasValue &&
Added into your where clause to filter out dobs that are null.
I'm assuming DateOfBirth is a nullable DateTime.