I have a view with computed columns now I need to enforce the computed columns to be "not null" for lightswitch.
I tried to cast() but I still cant get the computed columns to be "not null"
Is it possible?
This is my SQL:
SELECT dbo.Nop_Manufacturer.Name,
CAST(SUM(dbo.Nop_OrderProductVariant.PriceExclTax) AS INT) AS
SALES,
CAST(MONTH(dbo.Nop_Order.PaidDate) AS INT) AS
paid_month,
CAST(YEAR(dbo.Nop_Order.PaidDate) AS INT) AS
paid_year,
CAST(COUNT(dbo.Nop_OrderProductVariant.OrderProductVariantID) AS INT)AS
num_prod_sold
FROM dbo.Nop_ProductVariant
INNER JOIN dbo.Nop_OrderProductVariant
ON dbo.Nop_ProductVariant.ProductVariantId =
dbo.Nop_OrderProductVariant.ProductVariantID
INNER JOIN dbo.Nop_Product
ON dbo.Nop_ProductVariant.ProductID = dbo.Nop_Product.ProductId
INNER JOIN dbo.Nop_Product_Manufacturer_Mapping
INNER JOIN dbo.Nop_Manufacturer
ON dbo.Nop_Product_Manufacturer_Mapping.ManufacturerID =
dbo.Nop_Manufacturer.ManufacturerID
ON dbo.Nop_Product.ProductId =
dbo.Nop_Product_Manufacturer_Mapping.ProductID
INNER JOIN dbo.Nop_Order
ON dbo.Nop_OrderProductVariant.OrderID = dbo.Nop_Order.OrderID
WHERE ( NOT ( dbo.Nop_Order.PaidDate IS NULL ) )
GROUP BY dbo.Nop_Manufacturer.Name,
MONTH(dbo.Nop_Order.PaidDate),
YEAR(dbo.Nop_Order.PaidDate)
CAST-ing as INT won't do anything to affect the perceived nullability of computed columns. You need to wrap them in ISNULL instead.
e.g. ISNULL(YEAR(dbo.Nop_Order.PaidDate),0)
This is documented in the last paragraph here
The Database Engine automatically determines the nullability of
computed columns based on the expressions used. The result of most
expressions is considered nullable even if only nonnullable columns
are present, because possible underflows or overflows will produce
null results as well. Use the COLUMNPROPERTY function with the
AllowsNull property to investigate the nullability of any computed
column in a table. An expression that is nullable can be turned into a
nonnullable one by specifying ISNULL(check_expression, constant),
where the constant is a nonnull value substituted for any null result.
Related
I have four tables for a form-builder in my databse.
fields (fieldID(PK), typeID, fieldName, ...) - This table is a row by row list of all fields to be in the form
fields_types (typeID(PK), htmlType, ...) - This is a table that links fields to html types (and other settings)
fields_meta (FieldMetaID(PK), FieldID, mName, mValue) - Additional settings for fields, but more specific. A textarea field might have a height attribute, but almost no other field would use that.
fields_tyeps_meta (TypeMetaID(PK), typeID, tmName, tmValue) - Defines what extraneous settings a field can have, and also supplies default values if it's not explicitly set)
So my Query currently looks something like this
SELECT *
FROM Fields F
JOIN Field_Types FT
on FT.FieldID = F.FieldID
LEFT
JOIN Field_Meta FM
on FM.FieldID = F.FieldID
I was wondering if there's a way to join Fields_Types_Meta so that when the row's JOIN to Fields_Meta doesn't return a row (no mValue), it returns tmValue
I realize I can use something like (CASE WHEN mValue = "" THEN tmValue ELSE mValue END) AS UseValue, but I might have fields where I want to allow the value to be set to empty.
Edit: I could probably do something with a subquery and COUNT, using a CASE decision based on that. It might not be the healthiest performance-wise, but this query runs and caches itself til server restart, or until it's told to run again (updates to form design)
It looks like you just want ¢oalesce():
coalesce(FM.mValue, FT.tmValue) as UseValue
When FM.mValue is null, coalesce() returns FT.tmValue instead.
If you have null values in FM that you want to preserve in the result set, then use a case expression instead:
case when FM.FieldID IS NULL THEN FT.tmValue ELSE FM.mValue END as UseValue
This phrases as: when the left join did find a match in FM, use mValue from that row (even if it is null), else use FT.tmValue.
In MySQL, is there a way to set the "total" fields to zero if they are NULL?
Here is what I have:
SELECT uo.order_id, uo.order_total, uo.order_status,
(SELECT SUM(uop.price * uop.qty)
FROM uc_order_products uop
WHERE uo.order_id = uop.order_id
) AS products_subtotal,
(SELECT SUM(upr.amount)
FROM uc_payment_receipts upr
WHERE uo.order_id = upr.order_id
) AS payment_received,
(SELECT SUM(uoli.amount)
FROM uc_order_line_items uoli
WHERE uo.order_id = uoli.order_id
) AS line_item_subtotal
FROM uc_orders uo
WHERE uo.order_status NOT IN ("future", "canceled")
AND uo.uid = 4172;
The data comes out fine, except the NULL fields should be 0.
How can I return 0 for NULL in MySQL?
Use IFNULL:
IFNULL(expr1, 0)
From the documentation:
If expr1 is not NULL, IFNULL() returns expr1; otherwise it returns expr2. IFNULL() returns a numeric or string value, depending on the context in which it is used.
You can use coalesce(column_name,0) instead of just column_name. The coalesce function returns the first non-NULL value in the list.
I should mention that per-row functions like this are usually problematic for scalability. If you think your database may get to be a decent size, it's often better to use extra columns and triggers to move the cost from the select to the insert/update.
This amortises the cost assuming your database is read more often than written (and most of them are).
None of the above answers were complete for me.
If your field is named field, so the selector should be the following one:
IFNULL(`field`,0) AS field
For example in a SELECT query:
SELECT IFNULL(`field`,0) AS field, `otherfield` FROM `mytable`
Hope this can help someone to not waste time.
You can try something like this
IFNULL(NULLIF(X, '' ), 0)
Attribute X is assumed to be empty if it is an empty String, so after that you can declare as a zero instead of last value. In another case, it would remain its original value.
Anyway, just to give another way to do that.
Yes IFNULL function will be working to achieve your desired result.
SELECT uo.order_id, uo.order_total, uo.order_status,
(SELECT IFNULL(SUM(uop.price * uop.qty),0)
FROM uc_order_products uop
WHERE uo.order_id = uop.order_id
) AS products_subtotal,
(SELECT IFNULL(SUM(upr.amount),0)
FROM uc_payment_receipts upr
WHERE uo.order_id = upr.order_id
) AS payment_received,
(SELECT IFNULL(SUM(uoli.amount),0)
FROM uc_order_line_items uoli
WHERE uo.order_id = uoli.order_id
) AS line_item_subtotal
FROM uc_orders uo
WHERE uo.order_status NOT IN ("future", "canceled")
AND uo.uid = 4172;
I'm dealing with a situation at work where someone set up some tables without a primary key (arghhh). now I'm trying to compare dev data to prod data and the best I can tell is that theres a slight difference in the number of rows.
I figured the best way I could compare data is to do a join on every column, but I'm getting unexpected results.
to test this out I just joined the same table to itself. This table has 1309 rows.. but when I join on every column i get 1014. Thats less rows. If anything i'd expect to get more. What gives?
select *
from `default_tire_classifications` tc1
join `default_tire_classifications` tc2
on tc1.`marketing_tread_name` = tc2.`marketing_tread_name`
AND tc1.`size` = tc2.`size`
AND tc1.product_category = tc2.product_category
AND tc1.application = tc2.application
AND tc1.vehicle_type = tc2.vehicle_type
AND tc1.oem_part = tc2.oem_part
AND tc1.position = tc2.position
AND tc1.size = tc2.size
AND tc1.sect_wdth = tc2.sect_wdth
AND tc1.aspect_ratio = tc2.aspect_ratio
AND tc1.rim_size = tc2.rim_size
AND tc1.speed_rating = tc2.speed_rating
AND tc1.load_index = tc2.load_index
I suspect some of the columns contain NULL values. An equality comparison to a NULL value yields NULL. (SQL tri-valued Boolean logic.)
To do a comparison that yields TRUE when both sides are NULL, you could do something like this
( tc1.col = tc2.col OR ( tc1.col IS NULL AND tc2.col IS NULL ) )
MySQL also provides a non-standard "null-safe" equality comparison operator <=> (spaceship) that does the same thing.
tc1.col <=> tc2.col
returns either TRUE or FALSE, and will return TRUE when the values on both sides are NULL.
So, replacing the = (equality comparison) operator with <=> operator should resolve the problem with comparing NULL values.
(This isn't to say that NULL values is a problem, or is the only problem.)
If your fields contains NULL, you will lost them. Because NULL = NULL is not true.
I hava two very similar queries, however they return different result.
The first one:
select * from products p
where p.val >= 999999 and
not exists
(select * from products p2 where p2.val < 999999 and p.user_id = p2.user_id);
The second one:
select * from products p
where p.val >= 999999 and
p.user_id not in (select user_id from products p2 where p2.val < 999999);
The first one gave me the right answer, while the second one gave me no (zero) result. Is it possible that this happened because the subquery in the second query gave too many results?
Beware of nulls!
If there's a NULL in the sub-query, the NOT IN will not work as most people expect.
The issue will be clearer if you translate NOT IN (...) either to NOT (... OR ...) or to NOT ... AND NOT ... and apply the three-valued logic to the resulting expression.
To illustrate this with an example, let's say the condition is NOT IN (1, 2, NULL) and the row being checked has a value of 3.
Using NOT (... OR ...) you get this:
NOT (3=1 OR 3=2 OR 3=NULL)
The first two conditions in the brackets are false the last one is unknown. Based on the three-valued logic, the result of the disjunction will be unknown. Inversion of an unknown is also unknown, according to that same logic. The result of unknown in a WHERE clause is treated same as the result of false, i.e. a no-match. So, here you are.
Now, if you rewrite the NOT IN with NOT ... AND NOT ..., this is what you get:
NOT 3=1 AND NOT 3=2 AND NOT 3=NULL
The first two terms are true, the last one is unknown (3=NULL is unknown, its inversion is unknown as well). Again, the three-valued logic says the final result is unknown in this case. Here you are again.
So, when a row has a value that is not in the subset but the subset also contains nulls, either do not use NOT IN or filter out the nulls.
HI i am using this query below its taking hell lot of a time around like 5 mins .. its crazy .. any better way ? or reason fr such long time .. even cutting it into smaller query n getting the value n then finding the common values is much much faster then this.
SELECT Product_ItemID
FROM Product_ItemProperties
LEFT JOIN Product_Items USING (Product_ItemID)
WHERE
Product_CatalogueID = 'xx' AND
Field = 'brandname' AND
MATCH (Value) AGAINST ('xx' IN BOOLEAN MODE) AND
Product_ItemID IN (Select Product_ItemID
FROM Product_ItemProperties
Where Field = 'xx' AND
Match (Value) AGAINST ('xx' IN BOOLEAN MODE)
);
i dont know why in first where clause you are making Field = 'brandname' and in second inner where clause you are filtering by Field = 'xx' . anyway you are double selecting Product_ItemProperties while you should use it once.
try this:
SELECT
Product_ItemID
FROM
Product_ItemProperties
LEFT JOIN
Product_Items USING (Product_ItemID)
WHERE
Product_CatalogueID = 'xx'
AND Field = 'brandname'
AND MATCH (Value) AGAINST ('xx' IN BOOLEAN MODE)
AND Field = 'xx';
It looks like your itemProperties table has multiple entries for the same "Product_ItemID", and you are looking for something that is both "BrandX", AND has some "OtherProperty" of a different value. To handle this, you can use that table TWICE (or more if more property values you are interested in... I would suggest having an index on your Product_ItemProperties table by (Product_ItemID, Field, Value) to be best optimization of the query.
For example, you are looking for a Car Brand "X", and secondly, it is a "Blue" car (not considering the catalog component).
Also, notice in this query, I give simplified aliases, and qualify each field with the alias.field so there is no ambiguity which field is coming from where.
The outer WHERE clause is your first criteria, only get those items that have a minimum of the brand name field, and it matches the value you are expecting... From those, join again to the product item properties table, but for the "other" field value you are interested in, and its value.
I was unsure where the cataglog component was, but I suspect that's from the product table and should have ITs alias adjusted.
SELECT
ByBrand.Product_ItemID,
P.NameOfProduct, (just an example to get this too)
FROM
Product_ItemProperties ByBrand
JOIN Product_Items P
ON ByBrand.Product_ItemID = P.Product_ItemID
JOIN Product_ItemProperties ByOtherField
ON ByBrand.Product_ItemID = ByOtherField.Product_ItemID
AND ByOtherField.Field = 'otherPropertyInterestedIn'
AND MATCH (ByOtherField.Value) against ( 'otherValueLookingFor' IN BOOLEAN MODE )
WHERE
ByBrand.Product_CatalogueID = 'someCatalogID' (or is this from product_items table)
AND ByBrand.Field = 'brandname'
AND MATCH (ByBrand.Value) against ( 'brandValueLookingFor' IN BOOLEAN MODE )