I have a Customer table, my client want to not physically delete any record from this table so I use a TINYINT field "IsDeleted" to keep track of deleted customers.
Now i m in a situation where i need to exclude Deleted Customers but when i tired following Query it gives me less number of records
select count(*) from customer where IsDeleted <> 1; (Count = 1477)
then the following
select count(*) from customer where (IsDeleted = 0 or IsDeleted is null); (Count = 1552)
why the above query counts are different?
why "NULL" value is not counted in " IsDeleted <> 1" check?
Please suggest.
Like Duniyadnd and triclosan point out this is caused by the column type for IsDeleted.
Change the query in the right panel so you can see the difference between using int and varchar column types. sqlfiddle.com/#!2/7bf0a/5
You cannot correct use comparing operations for NULL-values. Consider to change type of IsDeleted to enum('N','Y') with Not NULL option.
Null is not an int. As soon as you did <> 1, that means it would only look at ints. Null ideally means something that does not exist (that's why a lot of people use it instead of 0 in case you do store 0s in the table).
If you only have null, 0 and 1 values in the isDeleted column, you would probably find a difference between the two queries (1522-1477) to be the total number of nulls in your table (75).
Related
I have a MySQL table or around 150,000 rows and a good half of them have a blob (image) stored in a longblob field. I'm trying to create a query to select rows and include a field that simply indicates that the longblob (image) is exists. Basically
select ID, address, IF(house_image != '', 1, 0) AS has_image from homes where userid='1234';
That query times out after 300 seconds. If I remove the 'IF(house_image != '', 1, 0)' it completes in less than a second. I've also tried the following, but they all time out.
IF(ISNULL(house_image),0,1) as has_image
LEFT (house_image,1) AS has_image
SUBSTRING(house_image,0,1) AS has_image
I am not a DBA (obviously), but I'm suspecting that the query is selecting the entire longblob to know if it's empty or null.
Is there an efficient way to know if a field is empty?
Thanks for any assistance.
I had similar problem long time ago and the workaround I ended up with was to move all blob/text columns into a separate table (bonus: this design allows multiple images per home). So once you've changed the design and moved the data around you could do this:
select id, address, (
select 1
from home_images
where home_images.home_id = homes.id
limit 1
) as has_image -- will be 1 or null
from homes
where userid = 1234
PS: I make no guarantees. Depending on storage engine and row format, the blobs could get stored inline. If that is the case then reading the data will take much more disk IO than needed even if you're not "select"ing the blob column.
It looks to me like you are treating the house_image column as a string when really you should be checking it for NULL.
select ID, address, IF(house_image IS NOT NULL, 1, 0) AS has_image
from homes where userid='1234';
LONGBLOBs can be indexed in MariaDB / MySQL, but the indexes are imperfect: they are so-called prefix indexes, and only consider the first bytes of the BLOB.
Try creating this compound index with a 20-byte prefix on your BLOB.
ALTER TABLE homes ADD INDEX user_image (userid, house_image(20));
Then this subquery will, efficiently, give you the IDs of rows with empty house_image columns.
SELECT ID
FROM homes
WHERE userid = '1234'
AND (house_image IS NULL OR house_image = '')
The prefix index can satisfy (house_image IS NULL OR house_image = '') directly without inspecting the BLOBs. That saves a whole mess of IO and CPU on your database server.
You can then incorporate your subquery into a main query to get your result.
SELECT h.ID, h.address,
CASE WHEN empty.ID IS NULL 1 ELSE 0 END has_image
FROM homes h
LEFT JOIN (
SELECT ID
FROM homes
WHERE userid = '1234'
AND (house_image IS NULL OR house_image = '')
) empty ON h.ID = empty.ID
WHERE h.userid = '1234'
The IS NULL ... LEFT JOIN trick means "any rows that do NOT show up in the subquery have images."
I want to update a whole table sav where the column phone contains the id from a table stock_phone. I want to set the sav.phonecolumn to the stock_phone.imei value, here is the query I tried:
UPDATE sav JOIN
stock_phone
ON sav.phone = stock_phone.id
SET sav.phone = stock_phone.imei;
But then the sav.phone value is set to 2147483647 for every row, and this value doesn't match with any imei value from stock_phone.
I search about how to UPDATE and JOIN but my syntax seems correct according to the questions I read.
Finally solved it myself..
I'm trying to set a too big integer into an INT(8) field. The 2147483647 value means Incorrect Integer, that's why the value isn't matching with one of my records.
Hope it will help some people.
2147483647 equals to 2^31-1 limit of INT(4). IMEI number (15 digits) are greater of this value.
I am curious if this returns the same results:
UPDATE sav s
SET s.phone = (SELECT sp.imei FROM stock_phone sp WHERE s.phone = sp.id);
I don't see a problem with updating the key used for the JOIN, but perhaps that is triggering some sort of bug.
This has been racking my head. I've scoured the internet (including this place) and can't find a solution. So as a last resort I was hoping the good people of this forum might be able to help me out.
I have two tables:
TableA
Order_detailsID
OrderID
TitleID
Return_date
TableB
TitleID
Title_name
Quantity_in_stock
And would like to run a query that shows the remaining 'Quantity_in_stock'.
If the 'Return_date' is set to NULL then it means the item is currently out -- so I have been trying to use the count() function for the NULL values and subtract it from the 'Quantity_in_stock'.
This is the script I have so far:
DELIMITER //
CREATE PROCEDURE InStock()
BEGIN
Select TableB.TitleID,
TableB.Title_name,
TableB.Quantity_in_stock AS 'Total_Stock',
COUNT(TableA.return_date IS NULL) AS 'Rented_Out',
TableB.Quantity_in_stock - COUNT(TableA.return_date IS NULL) AS 'Remaining Stock'
From TableB
LEFT JOIN TableA
ON TableA.TitleID = TableB.TitleID
GROUP BY TableB.TitleID;
END//
This works if there is one of more of the TitleIDs at NULL, however if there are no values at NULL, then the Count() is still returning a value of 1 when it should be 0.
What am I doing wrong?
Instead of:
COUNT(TableA.return_date IS NULL)
use this:
SUM(CASE
WHEN TableA.TitleID IS NULL THEN 0
WHEN TableA.return_date IS NOT NULL THEN 0
ELSE 1
END)
The problem with the TableA.return_date IS NULL predicate is that it's true in two completely different situations:
When there is no matching record in TableA
When there is a matching record but TableA.return_date value of this exact record is NULL.
Using the CASE expression you can differentiate between these two cases.
I will like to mention a simple concept here, just keep counting the rows when that particular column is null.
select count(*) from table_name where column_name is null
I have a table defined like the following...
CREATE table actions (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
end BOOLEAN,
type VARCHAR(15) NOT NULL,
subtype_a VARCHAR(15),
subtype_b VARCHAR(15),
);
I'm trying to query for the last end action of some type to happen on each unique (subtype_a, subtype_b) pair, similar to a group by (except SQLite doesn't say what row is guaranteed to be returned by a group by).
On an SQLite database of about 1MB, the query I have now can take upwards of two seconds, but I need to speed it up to take under a second (since this will be called frequently).
example query:
SELECT * FROM actions a_out
WHERE id =
(SELECT MAX(a_in.id) FROM actions a_in
WHERE a_out.subtype_a = a_in.subtype_a
AND a_out.subtype_b = a_in.subtype_b
AND a_in.status IS NOT NULL
AND a_in.type = "some_type");
If it helps, I know all the unique possibilities for a (subtype_a,subtype_b)
eg:
(a,1)
(a,2)
(b,3)
(b,4)
(b,5)
(b,6)
Beginning with version 3.7.11, SQLite guarantees which record is returned in a group:
Queries of the form: "SELECT max(x), y FROM table" returns the value of y on the same row that contains the maximum x value.
So greatest-n-per-group can be implemented in a much simpler way:
SELECT *, max(id)
FROM actions
WHERE type = 'some_type'
GROUP BY subtype_a, subtype_b
Is this any faster?
select * from actions where id in (select max(id) from actions where type="some_type" group by subtype_a, subtype_b);
This is the greatest-in-per-group problem that comes up frequently on StackOverflow.
Here's how I solve it:
SELECT a_out.* FROM actions a_out
LEFT OUTER JOIN actions a_in ON a_out.subtype_a = a_in.subtype_a
AND a_out.subtype_b = a_in.subtype_b
AND a_out.id < a_in.id
WHERE a_out.type = "some type" AND a_in.id IS NULL
If you have an index on (type, subtype_a, subtype_b, id) this should run very fast.
See also my answers to similar SQL questions:
Fetch the row which has the Max value for a column
Retrieving the last record in each group
SQL join: selecting the last records in a one-to-many relationship
Or this brilliant article by Jan Kneschke: Groupwise Max.
Greetings and thank you for looking at my question, I hope you can provide some insight or direction.
I have three tables (fundamentally): 'value_meta', 'value', and 'values_visibility'. The schema follows:
TABLE 'value_meta'
COMMENT: contains a list of different values, each referencing a different 'value' table
int id PK
tinyint value1 FK to value1.value
tinyint value2 FK to value2.value
tinyint value3 FK to value3.value
...
TABLE 'value'
COMMENT: there are different value tables (for example, if it were for user profile data, there would be a value table for "occupation", "body type", and/or "education level"
tinyint id PK
varchar(255) value
TABLE 'value_visibility'
COMMENT: one value visibility entry per value[n] in the 'value_meta' table, each a boolean value. If 1, the coding query will return the value as rerefenced in 'value[n]' table. if 0, return null
int id PK
BOOLEAN 'value1_visibility'
BOOLEAN 'value2_visibility'
BOOLEAN 'value3_visibility'
....
What I want to do is create a proper MySQL query to check "for each 'value' in 'value_meta', if corresponding value entry in 'value_visibility' is 1, display value varchar. else return null". By proper I want to make it most efficient (dereived tables vs. correlated subqueries, proper conditionals and function uses... I hear ISNULL is bad).
I used to be good at query building straight out of my mind back in college but after years of not using it, I've become three straws short of a full broom. Can anyone help me? Thanks!
SELECT vm.id,
IF(vv.id IS NULL, NULL, vm1v.value) value1,
IF(vv.id IS NULL, NULL, vm2v.value) value2,
IF(vv.id IS NULL, NULL, vm3v.value) value3
FROM value_meta vm
LEFT JOIN value vmv1 ON vm.value1 = vmv1.id
LEFT JOIN value vmv2 ON vm.value1 = vmv2.id
LEFT JOIN value vmv3 ON vm.value1 = vmv3.id
LEFT JOIN value_visibility vv ON vm.id = vv.id AND vv.value1_visibility = 1
You should think about restructuring your value_meta table, is there a reason why you are storing value1 2 and 3 in the same row?