I have a bql aggregate query that I want to group by the Year and the Month.
This would be simple enough in SQL, but not so obvious in BQL.
The table (DAC) has a date field in it.
If I group by the date field alone, it basically gives me each individual record.
I would like to group on the year in the date and the month in the date.
Does BQL have the ability to grab the DATEPART like in SQL and group by that DATEPART result?
I see it has a datediff function, but no documentation on what I would like to do.
I hope this works for you:
public sealed class DatePart
{
public const string Day = "dd";
public const string Hour = "hh";
public const string Minute = "mi";
public const string Month = "mm";
public const string Year = "yyyy";
public const string Second = "ss";
public const string Millisecond = "ms";
public class day : Constant<string> { public day() : base(Day) { } }
public class hour : Constant<string> { public hour() : base(Hour) { } }
public class minute : Constant<string> { public minute() : base(Minute) { } }
public class month : Constant<string> { public month() : base(Month) { } }
public class year : Constant<string> { public year() : base(Year) { } }
public class second : Constant<string> { public second() : base(Second) { } }
public class millisecond : Constant<string> { public millisecond() : base(Millisecond) { } }
}
public sealed class DatePart<UOM, Operand> : BqlFunction, IBqlOperand, IBqlCreator
where Operand: IBqlOperand
where UOM : Constant<string>, new()
{
private IBqlCreator _operand;
public void Verify(PXCache cache, object item, List<object> pars, ref bool? result, ref object value)
{
value = null;
object date1;
if (!getValue<Operand>(ref _operand, cache, item, pars, ref result, out date1) || date1 == null) return;
DateTime period = Convert.ToDateTime(date1);
switch ((string)new UOM().Value)
{
case DatePart.Day:
value = Convert.ToInt32(period.Day);
break;
case DatePart.Hour:
value = Convert.ToInt32(period.Hour);
break;
case DatePart.Minute:
value = Convert.ToInt32(period.Minute);
break;
case DatePart.Second:
value = Convert.ToInt32(period.Second);
break;
case DatePart.Millisecond:
value = Convert.ToInt32(period.Millisecond);
break;
case DatePart.Month:
value = Convert.ToInt32(period.Month);
break;
case DatePart.Year:
value = Convert.ToInt32(period.Year);
break;
}
}
public void Parse(PXGraph graph, List<IBqlParameter> pars, List<Type> tables, List<Type> fields,
List<IBqlSortColumn> sortColumns, StringBuilder text, BqlCommand.Selection selection)
{
if (graph != null && text != null)
{
text.Append(" DATEPART(").Append((string)new UOM().Value).Append(", ");
parseOperand<Operand>(ref _operand, graph, pars, tables, fields, sortColumns, text, selection);
text.Append(")");
}
else
{
parseOperand<Operand>(ref _operand, graph, pars, tables, fields, sortColumns, text, selection);
}
}
}
Note: this is specific for MsSQL and won't work for mySQL.
Related
How do I format a BQL query to use the 'like' sql functionality. I want to get all the rows where the first two characters of a particular field match a string variable.
Sql example:
Select item, customer, uom from table where uom like 'CA%'
Somethng like this :
public static class Constants
{
public class likeCA : Constant<string>
{
public likeCA() : base("CA%") { }
}
}
public PXSelect<MyTable,Where<MyTable.uom,Like<Constants.likeCA>>> MySelect;
[PXCacheName("Filter")]
[Serializable]
public class ItemFilter : IBqlTable
{
#region FullDescription
[PXString(IsUnicode = true, InputMask = "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC")]
[PXUIField(DisplayName = "Full Description")]
public virtual string Description { get; set; }
public abstract class fdescription : IBqlField { }
#endregion
#region SearchDescrWildcard
[PXString(IsUnicode = true)]
public virtual string SearchDescrWildcard
{
get
{
return SearchWildcardUtils.CreateWildcard(this.Description);
}
set
{
}
}
public abstract class searchDescrWildcard : IBqlField { }
#endregion
public class SearchWildcardUtils
{
public static bool IsSearchWildcardEmpty(string aSub)
{
return aSub == null || aSub == "" || new Regex("^[_\\?]*$").IsMatch(aSub);
}
public static string CreateWildcard(string text)
{
ISqlDialect sqlDialect = PXDatabase.Provider.SqlDialect;
if (SearchWildcardUtils.IsSearchWildcardEmpty(text))
{
return sqlDialect.WildcardAnything;
}
if (text[text.Length - 1] != '?' && text[text.Length - 1] != ' ')
{
text = $"?{text}?";
}
return Regex.Replace(Regex.Replace(text, "[ \\?]+$", sqlDialect.WildcardAnything), "[ \\?]", sqlDialect.WildcardAnything);
}
}
}
public PXSelect<MyTable, Where<MyTable.description, Like<Current<ItemFilter.searchDescrWildcard>>>> SelectMyTable; // Sql Table select
cmd.WhereAnd<Where<MyTable.description, Like<Current<ItemFilter.searchDescrWildcard>>>>();// BQL query select
I am writing my first web API controller so I am a bit of a noob in this area. I am trying to retrieve a list of data through a static class called CustomerDataSource:
public static class CustomerDataSource
{
public static List<Customer> customerData
{
get
{
Customer customer1 = new Customer() { name = "Bert", address = "London" };
Customer customer2 = new Customer() { name = "Jon", address = "New York" };
List<Customer> listCustomers = new List<Customer>();
listCustomers.Add(customer1);
listCustomers.Add(customer2);
return listCustomers;
}
}
}
public class Customer
{
public string name { get; set; }
public string address { get; set; }
}
I am a bit stuck with my ApiController because I am trying to sort the list either on 'name' or 'address' but using a string called 'field' does not compile. What would be a good implementation for a WebAPI controller GETmethod which provides for sorting on one of the Customer properties ?
public class ValuesController : ApiController
{
// GET api/values
public List<Customer> Get(string field)
{
var list = CustomerDataSource.customerData.OrderBy(field);
}
}
Create an extension method like below, then you can use it anywhere within the same namespace in your project.
public static class extensionmethods
{
public static IQueryable<T> OrderByPropertyName<T>(this IQueryable<T> q, string SortField, bool Ascending)
{
var param = Expression.Parameter(typeof(T), "p");
var prop = Expression.Property(param, SortField);
var exp = Expression.Lambda(prop, param);
string method = Ascending ? "OrderBy" : "OrderByDescending";
Type[] types = new Type[] { q.ElementType, exp.Body.Type };
var rs = Expression.Call(typeof(Queryable), method, types, q.Expression, exp);
return q.Provider.CreateQuery<T>(rs);
}
}
Then you can use it like:
public List<Customer> Get(string PropertyName)
{
var list = CustomerDataSource.customerData.AsQueryable().OrderByPropertyName("PropertyName",true).ToList();
}
Note:
Because the extension method uses IQueryable and returns IQuerybale, so you need to convert your List to IQueryable. Also you can order the list by ascending and descending order, just pass the boolean type value to the second parameter. The default is ascending.
You need to use a lambda expression.
if (field == "name")
var list = CustomerDataSource.customerData.OrderBy(d => d.name);
else if (field == "address")
var list = CustomerDataSource.customerData.OrderBy(d => d.address);
There's any way to save a complete datetime (with the milliseconds part) in a table storage?
I'm using a TableServiceContext to save my entities.
Thanks
public class YourEntity : TableEntity
{
public YourEntity(string partitionName, string id)
{
this.PartitionKey = partitionName;
this.RowKey = id;
}
public YourEntity() { }
private string _date = "";
public string CustomDate
{
get
{
return _date;
}
set
{
_date = value;
}
}
}
YourEntity entity = new YourEntity("sample", "1");
entity.CustomDate = DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss.ffffff");
Please don't get mad, I am amiting this is help on my homework but I like to learn this and can't find it anywhere. I have looked for it and couldn't find anything like it, idk if I am looking in all the wrong places or for the wrong thing I have two other classes inside my code and having trouble creating another class with class objectives inside of it, I will show what I attempted and see if yall can please help me out. Also, I want to make sure I am using the keyword " this" right in my other two classes. She wanted us to use this in our program and the comments are what we are told to do:
public class Person
{
private String lastName;
private String firstName;
//default constructor
public Person()
{
lastName= null;
firstName = null;
}
//two-parameter constructor
public Person(String lastName, String firstName)
{
this.lastName=lastName;
this.firstName=firstName;
}
//copy constructor
public Person(Person object2)
{
this.lastName=object2.lastName;
this.firstName=object2.firstName;
}
// standard accessor method for each of the two fields
public String getLastName(String lastName)
{
lastName = this.lastName;
return lastName;
}
public String getFirstName(String firstName)
{
firstName = this.firstName;
return firstName;
}
public void setLastName(String lastName)
{
this.lastName=lastName;
}
public void setFirstName(String firstName)
{
this.firstName=firstName;
}
//mutator method for both fields—using standard mutator methods
public void setName(String lastName,String firstName)
{
this.lastName= lastName;
this.firstName = firstName;
}
//toString method
public String toString()
{
String str = “Last Name: “ + lastName + “\nFirst Name: “ + firstName;
return str;
}
//equals method
public boolean equals(Person name2)
{
boolean status;
if (this.lastName.equals(name2.lastName) && this.firstName.equals(name2.firstName))
status = true;
else
status = false;
return status;
}
//copy method
public Person copy()
{
Person copyObject = new Person(lastName, firstName);
return copyObject;
}
}
public class Date
{
private int month;
private int day;
private int year;
//default constructor
public Date()
{
this (0,0,0);
}
//three-parameter constructor
public Date(int month, int day, int year)
{
this.month = month;
this.day = day;
this.year = year;
}
//copy constructor
public Date(Date object2)
{
this (object2.month, object2.day, object2.year);
}
//standard accessor method for each field
public int getMonth(int month)
{
month = this.month;
return month;
}
public int getDay(int day)
{
day = this.day;
return day;
}
public int getYear(int year)
{
year = this.year;
return year;
}
//standard mutator method for each field
public void setMonth(int month)
{
this.month = month;
}
public void setDay(int day)
{
this.day = day;
}
public void setYear(int year)
{
this.year = year;
}
//mutator method for both fields—using standard mutator methods
public void setDate(int month, int day, int year)
{
this.month = month;
this.day = day;
this.year= year;
}
//toString method
public String toString()
{
String str = "Date:" + month+ " " + day + ", " + year;
return str;
}
//equals method
public boolean equals (Date object2)
{
boolean status;
if (this.month == object2.month && this.day == object2.day && this.year == object2.year)
status = true;
else
status = false;
return status;
}
//copy method
public Date copy()
{
Date copyObject = new Date(month, day, year);
return copyObject;
}
}
And this is what I have been trying for my other class and It shows an ERROR:
public class PersonalInfo
{
private Person name;
private Date birthday;
private int idNumber;
// the default constructor
public PersonalInfo()
{
Person name = new Person();
Date birthday = new Date();
this.idNumber = 0;
}
// A constructor that passes 6 parameters
public PersonalInfo(String lastName, String firstName, int month, int day, int year, int idNumber )
{
Person name = new Person(lastName, firstName);
Date birthday= new Date(month, day, year);
this.idNumber = idNumber;
}
}
Please help! And thank you for looking
Since you haven't specified the language or the error message, this is only a qualified guess. If this isn't the actual problem, provide more details.
public PersonalInfo()
{
Person name = new Person();
Date birthday = new Date();
this.idNumber = 0;
}
You are declaring new local variables name and birthday here, rather than using the class members. That means the class members never get initialized, and I suspect that's what the error is trying to tell you.
The right way to do this is to just refer directly to the variables:
this.name = new Person();
this.birthday = new Date();
or, since this is implied when there is no local variable or parameter with the same name:
name = new Person();
birthday = new Date();
is there any problem with this kinda registration via structure map??
static public class ContainerBootstrapper
{
static public void BootstrapDefaultContainer(bool test = false)
{
StructureMap.ObjectFactory.Initialize(x =>
{
x.Scan(p =>
{
p.AssemblyContainingType<IPropertyType>();
p.AddAllTypesOf<IPropertyType>();
// p.AddAllTypesOf<IPropertyType>().NameBy(c => c.Name);
});
});
}
public interface IPropertyType : IIdentityObject, IPriority
{
string PropertyName { get; set; }
ObjectType ObjectType { get; }
string DisplayName { get; set; }
IEntityType EntityType { get; set; }
IList<IPropertyRuleObject> RuleObjects { get; set; }
void AddRuleObject(IPropertyRuleObject ruleObject);
}
public abstract class PropertyTypeBase : PersistentObject, IPropertyType
{
public PropertyTypeBase()
{
}
public PropertyTypeBase(string propertyName, string displayName)
{
PropertyName = propertyName;
DisplayName = displayName;
}
....
}
public class StringType : PropertyTypeBase
{
private ObjectType _objectType;
public StringType()
{
_objectType = new ObjectType(typeof(string));
}
public StringType(string propertyName, string displayName)
: base()
{
PropertyName = propertyName;
DisplayName = displayName;
}
public override ObjectType ObjectType
{
get { return _objectType; }
}
}
when ContainerBootstrapper.BootstrapDefaultContainer(); execute I see this line of error:
StructureMap Exception Code: 200
Could not find an Instance named "StringType" for PluginType Azarakhsh.Domain.Core.AdaptiveObjectModel.Interface.IPropertyType
the calling code:
public IPropertyType GetPropertyType(IIdentityObject identityObject, string name)
{
string[] Properties = name.Split('.');
object Result = identityObject;
foreach (var Property in Properties)
Result = Result.GetType().GetProperty(Property).PropertyType.Name;
IPropertyType propertyType = StructureMap.ObjectFactory.GetNamedInstance<IPropertyType> (Result + "Type");
if (propertyType==null)
throw new Exception("Property type not found");
return propertyType;
}
what is the problem?
You are trying to get a named instance, but from what I can see of the code you have provided, you dont name your instances. The line of code that name your instances is commented out.
But even if you would just use the ObjectFactory.GetInstance<IPropertyType>(); here, you would have got an error because structuremap dont know what constructor to use. There are several solutions to theis problem.
Change your design so you only have one constructor
Mark your default constructor with the [DefaultConstructor] attribute, then it will work.
You can register it with objectFactory manually with something like this:
x.For().Use().Ctor("propertyName").Is("someValue").Ctor("displayName").Is("someValue");
You can write a custom registrationconvention as described here