Pattern matching input in haskell - function

I have this piece of code
middleNumber:: Int -> Int -> Int -> Int
middleNumber a b c
| a == b && a == c = a
| a == b || a == c = a
| b == c = b
| b < a && a < c || c < a && a < b = a
| a < b && b < c || c < b && b < a = b
| otherwise = c
I want to use pattern matching to catch all other input pattern, I tried to use
middleNumber _ = error "Wrong input"
and
middleNumber _ _ _ = error "Wrong input"
But they seem do not work. Appreciate any helps!

The patterns a b c already match any possible arguments that your function may receive, so any patterns you add in addition to that would just be unreachable code. There simply are no other input patterns for you to catch.

It's not clear which input is "wrong".
However, the otherwise-guard always evaluates to True and thus it will catch all orhter cases.
If you really have cases that are wrong input, then you should replace the otherwise-guard by the right condition. Finally,
you can add as a last line, which will only be used if no guard evaluates to True.
middleNumber _ _ _ = error "Wrong input"
that is
middleNumber :: Int -> Int -> Int -> Int
middleNumber a b c
| a == b && a == c = a
| a == b || a == c = a
| b == c = b
| b < a && a < c || c < a && a < b = a
| a < b && b < c || c < b && b < a = b
| ...conditions for c being the middle number... = c
middleNumber _ _ _ = error "Wrong input"
If no guard evaluates to True the last line catches all other cases.

Related

The Chase Method

My relation R(A,B,C,R,S,T) which is broken down to:
R1(A, B, C)
R2(R,S,T, C)
with dependencies:
A --> B
B --> C
R --> S
S --> T
I want to check with the chase method wheter there is a lossless join or not. I think I understand other relations I have done with the method.
I want to know if I have understood the method correctly:
|----||----||----||----||----||----|
| A || B || C || R || S || T |
|----||----||----||----||----||----|
| a || b || c || r1 || s1 || t1 |
|----||----||----||----||----||----|
| a1 || b1 || c || r || s || t |
|----||----||----||----||----||----|
Is this a dead end? I'm I only allowed to remove a subscript if the letter on the left side of the dependency is not already subscripted?

Update Case When, with multiple conditions

I have this table:
CREATE TABLE IF NOT EXISTS `my_table` (
`A` int(11) NOT NULL,
`B` int(11) NOT NULL,
`C` varchar(50) NOT NULL,
`D` varchar(30) NOT NULL,
PRIMARY KEY (`A`,`B`,`C`)
)
I want to update several entries in just one query. I tried this:
UPDATE my_table
SET D = CASE
WHEN (A = 6 AND B = 1 AND C = 'red') THEN '1#2#3#5#4'
WHEN (A = 8 AND B = 1 AND C = 'green') THEN '5#6#7#8#9'
END
But this query updates all entries in the table. It updates perfectly the value of 'D' of the two entries I want to update, but it also deletes the values of "D" of the other entries, and I want them to stay with their previous values.
If you do not explicitly add an else clause to a case expression, it implicitly acts as though you've added else null to it. So, your update statement is effectively equivalent to:
UPDATE my_table
SET D = CASE
WHEN (A = 6 AND B = 1 AND C = 'red') THEN '1#2#3#5#4'
WHEN (A = 8 AND B = 1 AND C = 'green') THEN '5#6#7#8#9'
ELSE NULL
END
Which explains why you see D being "deleted".
One way around it is to explicitly add an else clause that simply returns D:
UPDATE my_table
SET D = CASE
WHEN (A = 6 AND B = 1 AND C = 'red') THEN '1#2#3#5#4'
WHEN (A = 8 AND B = 1 AND C = 'green') THEN '5#6#7#8#9'
ELSE D
END
Another way, which is a bit "clunkier" in syntax, but may perform slightly better, is to add a where clause so only the relevant rows are updated:
UPDATE my_table
SET D = CASE
WHEN (A = 6 AND B = 1 AND C = 'red') THEN '1#2#3#5#4'
WHEN (A = 8 AND B = 1 AND C = 'green') THEN '5#6#7#8#9'
END
WHERE (A = 6 AND B = 1 AND C = 'red') OR (A = 8 AND B = 1 AND C = 'green')

Haskell Location Definition "No instance for (Fractional Int) arising from a use of ‘/’"

I'm getting the error "No instance for (Fractional Int) arising from a use of ‘/’", from inside a local definition in a function I'm trying to make which determines how many of the (three) given integers are above the average of all of the given integers. So I've created a local definition inside the function to calculate the average so I can then use it for guard checks. I've used the same code in a separate definition (in another file) to calculate the average and it works. I've tried putting the "fromIntegral" function call in different places but it's not working, where am I going wrong?
Here's the code:
howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
| a > average && b > average = 2
| a > average && c > average = 2
| b > average && c > average = 2
| a > average = 1
| b > average = 1
| c > average = 1
| otherwise = 0
where
average = fromIntegral (a + b + c) / 3
The error is being flagged up on the last line.
Thanks.
Here's a cleaner version of the solution you came up with:
howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
| a' > average && b' > average = 2
| a' > average && c' > average = 2
| b' > average && c' > average = 2
| a' > average = 1
| b' > average = 1
| c' > average = 1
| otherwise = 0
where
average = a' + b' + c' / 3
a' = fromIntegral a
b' = fromIntegral b
c' = fromIntegral c
You can simplify this even further to:
howManyAboveAverage a b c = length (filter (> average) [a', b', c'])
where
average = a' + b' + c' / 3
a' = fromIntegral a
b' = fromIntegral b
c' = fromIntegral c
You're comparing a (which is an Int) and average (which is Fractional a => a). Since (>) :: a -> a Bool, GHC presumes that average is also an Int, which doesn't work. You either need to change average to Int (for example via round) or a, b and c to Double or Float.
You can also compare integers instead. The idea is that x < (a + b + c)/3 is equivalent to 3*x < a + b + c.
howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
| gti a av && gti b av = 2
| gti a av && gti c av = 2
| gti b av && gti c av = 2
| gti a av = 1
| gti b av = 1
| gti c av = 1
| otherwise = 0
where
av = a + b + c
gti x m = 3*x > m
I've managed to resolve this by adding "fromIntegral" in front of any parameter that was compared to the average.
New (working) code:
howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
| fromIntegral a > average && fromIntegral b > average = 2
| fromIntegral a > average && fromIntegral c > average = 2
| fromIntegral b > average && fromIntegral c > average = 2
| fromIntegral a > average = 1
| fromIntegral b > average = 1
| fromIntegral c > average = 1
| otherwise = 0
where
average = fromIntegral (a + b + c) / 3
It looks a bit messy / cumbersome so if anyone has any other (cleaner) suggestions please let me know.

MySQL view taking forever

MySQL server 5.6
innodb_buffer_pool_size = 6GB
key_buffer_size = 20M
Here is my schema:
TBL_1 TBL_2 TBL_3 TBL_4 TBL_5 TBL_6
id id id id id id (int, primary key, auto increment)
uid uid uid uid uid uid (varchar 100, key index)
dev dev dev dev dev dev (varchar 80)
intf intf intf intf intf intf (varchar 100)
stat1 stat2 stat3 stat4 stat5 stat6 (float, 11)
The uid field provides the unique relationship across the table rows.
count(*) across all tables is ~52K
My desired view:
VIEW_1
dev intf stat1 stat2 stat3 stat4 stat5 stat6
Here is an example of the view select sql I've tried thus far:
select a.dev, a.intf, a.stat1, b.stat2, c.stat3, d.stat4, e.stat_5, f.stat_6
from TBL_1 a
inner join TBL_2 b on b.uid = a.uid
inner join TBL_3 c on c.uid = a.uid
inner join TBL_4 d on d.uid = a.uid
inner join TBL_5 e on e.uid = a.uid
inner join TBL_6 f on f.uid = a.uid
Once I get beyond 2 joins the query becomes unresponsive. For the above query explain return
|| *id* || *select_type* || *table* || *type* || *possible_keys* || *key* || *key_len* || *ref* || *rows* || *Extra* ||
|| 1 || SIMPLE || e || ALL || uid || || || || 51391 || ||
|| 1 || SIMPLE || c || ref || uid || uid || 102 || db.e.uid || 1 || Using index condition ||
|| 1 || SIMPLE || a || ref || uid || uid || 102 || db.c.uid || 1 || ||
|| 1 || SIMPLE || b || ref || uid || uid || 257 || db.c.uid || 1 || Using index condition ||
|| 1 || SIMPLE || f || ref || uid || uid || 257 || db.c.uid || 1 || Using index condition ||
|| 1 || SIMPLE || d || ref || uid || uid || 102 || db.e.uid || 1 || Using index condition ||
Any suggestions on how this could be improved?
Check explain plan for the query
EXPLAIN SELECT * from ABC;
Check this Understanding the Query Execution Plan
As per output of explain consider adding indexes or using other Optimizing techniques
If this does not help paste your explain plan to look further.
Cheers !!

find the manager of sales employee

my table is 'DESIGNATION'
ID || DEPT_ID || E_NAME || DESIGNATION
1 || 12 || A || EMPLOYEE
2 || 12 || B || MANAGER
3 || 12 || C || EMPLOYEE
4 || 14 || D || MANGER
5 || 14 || E || EMPLOYEE
6 || 14 || F || EMPLOYEE
I want the manager name through their DEPT_NAME....
Mean result will look like
ID || DEPT_ID || E_NAME || DESIGNATION || MANAGER
1 || 12 || A || EMPLOYEE || B
2 || 12 || B || MANAGER || B
3 || 12 || C || EMPLOYEE || B
4 || 14 || D || MANGER || D
5 || 14 || E || EMPLOYEE || D
6 || 14 || F || EMPLOYEE || D
My query is
SELECT `ID`,`DEPT_ID`,`ENAME`,`DESIGNATION`,
(select `ENAME` from `DESIGNATION` where
(select `E_NAME` from `DESIGNATION` where
(SELECT `DEPT_ID` FROM `DESIGNATION` WHERE `DESIGNATION` = 'EMPLOYEE')
=
(SELECT `DEPT_ID` FROM `DESIGNATION` WHERE `DESIGNATION` = 'MANAGER') and `DESIGNATION`='MANAGER')
AS MANAGER
from `DESIGNATION`
but its not working...
You just need a JOIN operation. This is a basic concept when working with database. You should take some time reading about it.
Something like that?
SELECT A.*, B.E_NAME
FROM DESIGNATION AS A, DESIGNATION AS B
WHERE B.DESIGNATION = "MANAGER"
AND A.DEPT_ID = B.DEPT_ID
Or using explicit JOIN syntax:
SELECT A.*, B.E_NAME
FROM DESIGNATION AS A JOIN DESIGNATION AS B USING (DEPT_ID)
WHERE B.DESIGNATION = "MANAGER"
EDIT:
If you could have multiple managers, you could use the GROUP_CONCAT aggregate functions with explicit group by E_NAME (assuming this is an unique key):
SELECT A.*, GROUP_CONCAT(B.E_NAME)
FROM DESIGNATION AS A, DESIGNATION AS B
WHERE B.DESIGNATION = "MANAGER"
AND A.DEPT_ID = B.DEPT_ID
GROUP BY(A.E_NAME)
Old-school join syntax - sorry - but your sub queries don't make much sense.
Select d.ID,
d.DEPT_ID,
d.E_NAME,
d.DESIGNATION
m.MANAGER
from designation d,
designation m
where d.dept_id = m.dept_id
and m.designation = 'MANAGER'
This looks like a better job for whatever server-side script you're running. For example, in PHP, you can do this:
$managers = []; // array() before version 5.4
$employees = []; // see above comment
$query = "SELECT * FROM `DESIGNATION`";
$result = mysql_query($query); // adjust according to extension of choice
while($row = mysql_fetch_assoc($result)) { // same as previous comment
$employees[] = $row;
if( $row['DESIGNATION'] == "MANAGER") $managers[$row['DEPT_ID']] = $row['E_NAME'];
}
foreach($employees as $i=>$e) {
$employees[$i]['MANAGER'] = $managers[$e['DEPT_ID']] ?: "Nobody";
}
A simple JOIN will help, I prefer an explicit JOIN instead of the implicit comma notation:
SELECT `ID`,`DEPT_ID`,`E_NAME`,`DESIGNATION`, m.e_name, AS `MANAGER`
FROM `DESIGNATION` e
INNER JOIN `DESIGNATION` m
ON e.dept_id = m.dept_id
WHERE m.designation = 'MANAGER'
Can't we simply do this, in more simpler way ?
SELECT ID,DEPT_ID,ENAME,DESIGNATION,
case
when DEPT_ID=12 then 'B'
when DEPT_ID=14 then 'D'
end "MANAGER"
from DESIGNATION
Try the following
SELECT t.id
,t.dept_id
,t.e_name
,t.designation
,ta.e_name As Manager FROM Table1 t JOIN (SELECT e_name,dept_id
FROM Table1 WHERE designation = 'MANAGER'
GROUP BY dept_id,e_name) ta ON ta.dept_id = t.dept_id
SQLFiddle Demo