What is the best way to perform set operations using DBIx::Class?
I saw that one solution would be to create a Result Source based on my query, but my conditions will be defined by the user and I don know if the best answer is to create the result source on the fly.
Basically i need to translate this type of query to DBIC where code, attr_name and value is defined by the user:
SELECT pid FROM product WHERE code = 48
INTERSECT
(
( SELECT pid FROM attr WHERE attr_name = 'color' AND value = 'blue'
INTERSECT
SELECT pid FROM attr WHERE attr_name = 'size' AND value = 'big'
)
UNION
( SELECT pid FROM attr WHERE attr_name = 'color' AND value = 'green'
INTERSECT
SELECT pid FROM attr WHERE attr_name = 'size' AND value = 'small'
)
)
Could DBIx::Class::Helper::ResultSet::SetOperations be what you need?
Related
The following query
SELECT jsonb_build_array(jsonb_build_object('use', 'Home'),
CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work')
END)
produces
[{"use":"Home"},null]
When I actually want
[{"use":"Home"}]
How do I go about doing this? json_strip_nulls() does not work for me.
By using a PostgreSQL array like that:
SELECT array_to_json(array_remove(ARRAY[jsonb_build_object('use', 'Home'),
CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END], null))
which does produce:
[{"use": "Home"}]
while, to be sure:
SELECT array_to_json(array_remove(ARRAY[jsonb_build_object('use', 'Home'),
CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END,
jsonb_build_object('real_use', 'NotHome')], null))
does produce:
[{"use": "Home"},{"real_use": "NotHome"}]
Creating a custom function seems to be the simplest way.
create or replace function jsonb_build_array_without_nulls(variadic anyarray)
returns jsonb language sql immutable as $$
select jsonb_agg(elem)
from unnest($1) as elem
where elem is not null
$$;
select
jsonb_build_array_without_nulls(
jsonb_build_object('use', 'home'),
case when 1 = 2 then jsonb_build_object('use', 'work') end
)
jsonb_build_array_without_nulls
---------------------------------
[{"use": "home"}]
(1 row)
I'm assuming this query is generaetd dynamically, somehow. If you're in control of the SQL generation, you can also use ARRAY_AGG(...) FILTER(...) instead, which, depending on your real world query, might be more convenient than using all the different array conversion functions suggested by Patrick.
SELECT (
SELECT json_agg(v) FILTER (WHERE v IS NOT NULL)
FROM (
VALUES
(jsonb_build_object('use', 'Home')),
(CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END)
) t (v)
)
Or also:
SELECT (
SELECT json_agg(v)
FROM (
VALUES
(jsonb_build_object('use', 'Home')),
(CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END)
) t (v)
WHERE v IS NOT NULL
)
One other way that this can be handled is the following:
SELECT jsonb_build_array(
jsonb_build_object('use', 'Home'),
CASE
WHEN 1 = 2 THEN jsonb_build_object('use', 'Work')
ELSE '"null"'
END
) - 'null'
(Unfortunately it's not really possible to do much with null by itself in postgres -- or most other DBs)
In the case above, '"null"' could be replaced with just about any unique string that would not be mistaken for live data in the array. I would not use numbers since - 0 would actually try to remove the first item from the array, rather than a number within the array. But you could probably use '"0"' and remove using something like - '0' if you wanted.
For those not using CASE, a COALESCE could be used to convert nulls into the desired string (alas, no NVL, IFNULL or ISNULL in postgres, but at least COALESCE is portable)
Given below is my Model definition and I have added this module part of the Admin. I'm trying to create new row and while selecting value '3' or any other value for Duration field(listed as select fields), I get the following error.- "Value 3 is not a valid choice".
Please provide your inputs.
Model Definition
NO_OF_HRS = (
('1','One'),
('2','Two'),
('3','Three'),
('4','Four'),
('5','Five'),
('6','Six'),
('7','Seven'),
('8','Eight'),
('9','Nine'),
('10','Ten'),
('11','Eleven'),
('12','Twelve'),
)
YR_MONTH = (
("Y", "Year"),
("M", "Month"),
)
POS_STATUS = (
("A", "Active"),
("C", "Closed"),
)
datecreated = models.DateTimeField()
volposition = models.CharField(max_length=300)
roledesc = models.CharField(max_length=5000)
noofhours = models.IntegerField(blank = True,null = True)
Qualreqt = models.CharField(max_length=8000)
Duration = models.IntegerField(choices=NO_OF_HRS,blank = True,null = True)
Durationyrmon = models.CharField(choices=YR_MONTH,max_length=10)
posstatus = models.CharField(choices=POS_STATUS,max_length=1)
teamrelation = models.CharField(max_length=50)
When you use choices, the first value of the tuple is the value that will be stored in the database and the second value is the value that will be shown in the admin.
In NO_OF_HRS the values are strings (for example '1', '2') but it is a models.IntegerField so the values should be integers. That's why you're now getting an error.
Opened a ticket on django with fix and dirty fix:
https://code.djangoproject.com/ticket/24897
I'm trying to create a calculated member that returns a string of the value when there is only one distinct child, "Multi" when there are is more than one distinct child, and "None" when there are no children.
Specifically, I'm having trouble returning the case where there is on distinct child name. Here is my calculated measure:
WITH MEMBER [Measures].[SSN] AS
CASE
WHEN DISTINCTCOUNT([Item].[Season Code Name].Children) = 0
Then 'None'
WHEN DISTINCTCOUNT([Item].[Season Code Name].Children) = 1
Then [Item].[Season Code Name].FirstChild.Name --.Value is null
ELSE
'Multi'
END
The else returns a blank, but if I use [Item].[Season Code Name] in the crossjoin, the children show up as expected.
What am I doing wrong?
Thanks in advance for your help!
This is a classical, I do that all the times :-), missing currentMember after the hierarchy.
WITH MEMBER [Measures].[SSN] AS
CASE
WHEN DISTINCTCOUNT([Item].[Season Code Name].currentmember.Children() ) = 0
Then 'None'
WHEN DISTINCTCOUNT([Item].[Season Code Name].currentmember.Children() ) = 1
Then [Item].[Season Code Name].currentmember.FirstChild.Name --.Value is null
ELSE
'Multi'
END
Report needs option to select multiple super product types
Selection of multiple super product types?
IF #superProductType = 'ALL'
INSERT INTO #ProductDetails
SELECT pt_sp_type_c, pt_sb_type_c
FROM product..p_type_p_type
WHERE pt_sp_type_c NOT IN ('EQUITY','OPTEQTY')
AND p_type_use_sp_c= 'RPCDB'
AND p_type_use_sb_c = 'TRD'
AND pt_rel_stat_c = 'ACTIVE'
ELSE
INSERT INTO #ProductDetails
SELECT pt_sp_type_c, pt_sb_type_c
FROM product..p_type_p_type
WHERE pt_sp_type_c NOT IN ('EQUITY','OPTEQTY')
AND pt_sp_type_c IN (#superProductType)
AND p_type_use_sp_c= 'RPCDB'
AND p_type_use_sb_c = 'TRD'
AND pt_rel_stat_c = 'ACTIVE'
I have a parameter here #super product type,can anyone help me how to change this code
Here in this code i need to make some changes: ---parameter is #superProductType
The above code was for the option to select multiple super product types
when i select All and one value from the drop down list like 'ALL','ASKF'
both the above conditions in the code if else will fail
It should not get selected ALL and other ASKF at the same time
either should has to select
How can we differentiate that ALL not selecting ALL from together
if we select ALL remaining values in the drop down list must be deleted
It should not have two values selected together IF ALL only ALL has to select remaining should discard
I am not sure how to eliminate the rest of values in the drop down list
looking for suitable solution,can anybody see the code abnove and tell me what is the change i have to do in the code.
If you have set the SSRS parameter to Multivalue then you should change the query to use IN (#ParamName) syntax. so your query would become:
IF #superProductType = 'ALL'
INSERT INTO #ProductDetails
SELECT pt_sp_type_c, pt_sb_type_c
FROM product..p_type_p_type
WHERE pt_sp_type_c NOT IN ('EQUITY','OPTEQTY')
AND p_type_use_sp_c= 'RPCDB'
AND p_type_use_sb_c = 'TRD'
AND pt_rel_stat_c = 'ACTIVE'
ELSE
INSERT INTO #ProductDetails
SELECT pt_sp_type_c, pt_sb_type_c
FROM product..p_type_p_type
WHERE pt_sp_type_c NOT IN ('EQUITY','OPTEQTY')
AND pt_sp_type_c IN ( #superProductType )
AND p_type_use_sp_c= 'RPCDB'
AND p_type_use_sb_c = 'TRD'
AND pt_rel_stat_c = 'ACTIVE'
#HistoryMSBType => This is a variable which can contain any varchar.
Depending upon it's value, i need to have different type of where clause.
How can I achieve this ?
SELECT * FROM stageTable map
WHERE id = 1
CASE #HistoryMSBType
WHEN 'Utilization Other' THEN
AND map.ColumnID = 4
WHEN 'Cost Other' THEN
AND map.ColumnID = 6
ELSE
AND map.ColumnName = #HistoryMSBType
END
SELECT *
FROM stageTable map
WHERE id = 1
AND (
(#HistoryMSBType = 'Utilization Other' AND map.ColumnID = 4)
OR
(#HistoryMSBType = 'Cost Other' AND map.ColumnID = 6)
OR
(isnull(#HistoryMSBType,'') NOT IN ('Utilization Other','Cost Other')
AND map.ColumnName = #HistoryMSBType)
)
You need the ISNULL to make it match the CASE-ELSE exactly, but it won't matter if it can never be null.