I have a user function that returns a BIT calle dbo.IsPartReady.
I am trying to use the function inside of a trigger as follows:
SET #railReady = dbo.IsPartReady(1,#curPartiId);
SET #frameReady = dbo.IsPartReady(2,#curPartiId);
SET #dryAReady = dbo.IsPartReady(3,#curPartiId);
SET #dryBReady = dbo.IsPartReady(4,#curPartiId);
IF ( (#railReady AND #frameReady ) OR ( #dryAReady AND #dryBReady ) )
I'm getting the following error in the IF statement:
An expression of non-boolean type specified in a context where a condition is expected, near 'AND'.
What am I doing wrong ?
BIT data type in SQL Server is not a boolean it is an integer. You have to compare the value of the variable with something to get a boolean expression. BIT can have the value 0, 1 or NULL.
http://msdn.microsoft.com/en-us/library/ms177603.aspx
declare #B bit = 1
if #B = 1
begin
print 'Yes'
end
Use the following:
IF ((#railReady = 1 AND #frameReady = 1) OR (#dryAReady = 1 AND #dryBReady = 1))
or alternatively,
IF ((#railReady & #frameReady) | (#dryAReady & #dryBReady)) = 1
More information:
To verify this we can use a truth table containing all combinations of four bit values:
WITH B(x) AS (SELECT CAST(0 AS bit) UNION ALL SELECT CAST(1 AS bit))
, AllSixteenCombinations(a,b,c,d) AS
(SELECT * FROM B B1 CROSS JOIN B B2 CROSS JOIN B B3 CROSS JOIN B B4)
SELECT a,b,c,d
, CASE WHEN ((a = 1 AND b = 1) OR (c = 1 AND d = 1)) THEN 'Y' ELSE 'N' END[Logic]
, CASE WHEN ((a & b) | (c & d)) = 1 THEN 'Y' ELSE 'N' END [Bitwise]
FROM AllSixteenCombinations
Output:
a b c d Logic Bitwise
----- ----- ----- ----- ----- -------
0 0 0 0 N N
0 1 0 0 N N
0 0 1 0 N N
0 1 1 0 N N
1 0 0 0 N N
1 1 0 0 Y Y
1 0 1 0 N N
1 1 1 0 Y Y
0 0 0 1 N N
0 1 0 1 N N
0 0 1 1 Y Y
0 1 1 1 Y Y
1 0 0 1 N N
1 1 0 1 Y Y
1 0 1 1 Y Y
1 1 1 1 Y Y
(16 row(s) affected)
Related
I have a matrix B and I would like to obtain a new matrix C from B by adding its last w*a rows to the first w*a rows (w and a will be defined afterwards).
My matrix B is generally defined by :
I would like to obtain matrix C defined in a general way by:
The characteristics of matrices B and C are:
L and w are defined real values;
B0,B1,...,Bw are of dimension: a by b;
B is of dimension: [(L+w)×a] by (L×b);
C is of dimension: (L×a) by (L×b).
Example: For L = 4 and w = 2 I obtain the following matrix B:
The w*a = 2*1 = 2 last rows of B are:
The w*a = 2*1 = 2 first rows of B are:
By adding the two matrices we have:
The matrix C thus obtained is then:
For B0 = [1 0], B1 = [0 1] and B2 = [1 1]. We obtain :
B0, B1 and B2 are of dimension a by b i.e. 1 by 2;
B is of dimension: [(L+w )×(a)] by (L×b) i.e. [(4+2)×1] by (4×2) i.e. 6 by 8;
C is of dimension: (L×a) by (L×b) i.e. (4×1) by (4×2) i.e. 4 by 8.
The matrices B and C that I get are as follows:
B =
1 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0
1 1 0 1 1 0 0 0
0 0 1 1 0 1 1 0
0 0 0 0 1 1 0 1
0 0 0 0 0 0 1 1
C =
1 0 0 0 1 1 0 1
0 1 1 0 0 0 1 1
1 1 0 1 1 0 0 0
0 0 1 1 0 1 1 0
I would like to have some suggestions on how to program this construction so that from a given matrix B I can deduce the matrix C.
Matlab's range indexing should help you do this in a few steps. The key things to remember are that ranges are inclusive, i.e. A[1:3] is a three 3x1 matrix, and that you can use the keyword end to automatically index the end of the matrix row or column.
%% Variables from OP example
w = 2;
L = 4;
B0 = [1 0];
B1 = [0 1];
B2 = [1 1];
[a, b] = size(B0);
% Construct B
BX = [B0;B1;B2]
B = zeros((L+w)*a, L*b);
for ii = 0:L-1
B(ii+1:ii+w+1, ii*b+1:ii*b+b) = BX;
end
%% Construct C <- THIS PART IS THE ANSWER TO THE QUESTION
% Grab first rows of B
B_first = B(1:end-w*a, :) % Indexing starts at first row, continues to w*a rows before the end, and gets all columns
% Grab last rows of B
B_last = B(end-w*a+1:end, :); % Indexing starts at w*a rows before the end, continues to end. Plus one is needed to avoid off by one error.
% Initialize C to be the same as B_first
C = B_first;
% Add B_last to the first rows of C
C(1:w*a, :) = C(1:w*a, :) + B_last;
I get the output
C =
1 0 0 0 0 0 1 1 0 1
0 1 1 0 0 0 0 0 1 1
1 1 0 1 1 0 0 0 0 0
0 0 1 1 0 1 1 0 0 0
0 0 0 0 1 1 0 1 1 0
I have a given matrix H and I would like to unfold (expand) it to find a matrix B by following the method below :
Let H be a matrix of dimension m × n. Let x = gcd (m,n)
The matrix H is cut in two parts.
The cutting pattern being such that :
The "diagonal cut" is made by alternately moving c = n/x units to the right (we move c units to the right several times).
We alternately move c-b = m/x units down (i.e. b = (n-m)/x) (we move b units down several times).
After applying this "diagonal cut" of the matrix, we copy and paste the two parts repeatedly to obtain the matrix B.
Exemple : Let the matrix H of dimension m × n = 5 × 10 defined by :
1 0 1 1 1 0 1 1 0 0
0 1 1 0 0 1 1 0 1 1
1 1 0 1 1 1 0 1 0 0
0 1 1 0 1 0 1 0 1 1
1 0 0 1 0 1 0 1 1 1
Let's calculate x = gcd (m,n) = gcd (5,10) = 5,
Alternatively move to the right : c = n/x = 10/5 = 2,
Alternatively move down : b = (n-m)/x = (10-5)/5 = 1.
Diagonal cutting diagram : The matrix H is cut in two parts.
The cutting pattern is such that :
We move c = 2 units to the right several times c = 2 units to the right,
We repeatedly move c - b = 1 unit downwards.
We get :
After applying this "diagonal cut" of the matrix, we copy and paste the two parts repeatedly to obtain the matrix :
Remark : In the matrices X, X1 and X2 the dashes are zeros.
The resulting matrix B is (L is factor) :
Any suggestions?
This can be done by creating a logical mask with the cutting pattern, and then element-wise multiplying the input by the mask and by its negation. Repeating by L can be done with blkdiag.
H = [1 0 1 1 1 0 1 1 0 0
0 1 1 0 0 1 1 0 1 1
1 1 0 1 1 1 0 1 0 0
0 1 1 0 1 0 1 0 1 1
1 0 0 1 0 1 0 1 1 1];
L = 2;
[m, n] = size(H);
x = gcd(m, n);
c = n / x;
b = (n-m)/x;
mask = repelem(tril(true(m/b)), b, c);
A = [H.*mask; H.*~mask];
A = repmat({A}, L, 1);
B = blkdiag(A{:});
I am trying to get the most consecutive wins for a team. Firstly I have specified the win and lost results for every team but I have no idea how to get the most consecutive wins for the team
MATCH (a:TeamFootbal )-[r]->(m:Games)<-[r2]-(op:TeamFootbal)
with a.name as teamnames,
case when r.scores > r2.scores then 1 else 0 end as result
return teamnames, result
order by teamnames
The output will be like this
Team Name Result
A 1
A 1
A 1
A 0
A 1
B 1
B 1
B 1
B 1
B 0
C 1
C 0
C 1
C 1
C 0
D 0
D 1
D 0
D 0
D 1
E 1
E 1
E 1
E 1
E 0
I want to get
B 4
E 4
without using the apoc procedure
I adapted my answer to a similar question:
MATCH (a:TeamFootbal)-[r]->(m:Games)<-[r2]-(op:TeamFootbal)
WITH
a.name AS teamname,
CASE WHEN r.scores > r2.scores THEN 1 ELSE 0 END AS result
ORDER BY m.date ASC // (*)
WITH teamname AS s, collect([teamname, result]) AS p
WITH s, reduce(acc = [], i IN range(0, size(p) - 1) |
CASE p[i] = p[i-1]
WHEN true THEN [j IN range(0, size(acc) - 1) |
CASE j = size(acc) - 1
WHEN true THEN acc[j] + [p[i]]
ELSE acc[j]
END
]
ELSE acc + [[p[i]]]
END
) AS streaks
UNWIND streaks AS streak
WITH s, streak
WHERE streak[0] <> 0
RETURN s, max(size(streak)) AS consecutivePasses
Note that ordering should be inserted at (*)
Here is a little trick to search the max number of following 1 in a list :
WITH [1,0,0,1,1,1,0,1,1,1,1] AS results
RETURN
reduce(
// current value, highest value so far
x=[0,0],
i IN results |
CASE
WHEN i=0 THEN [0 , x[1]]
WHEN (x[0]+i) > x[1] THEN [x[0] +1 , x[0]+1]
ELSE [x[0] +1 , x[1]]
END
)
I have a logical matrix A, and I would like to select all the elements to the left of each of my 1s values given a fixed distant. Let's say my distance is 4, I would like to (for instance) replace with a fixed value (saying 2) all the 4 cells at the left of each 1 in A.
A= [0 0 0 0 0 1 0
0 1 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 1 0 1]
B= [0 2 2 2 2 1 0
2 1 0 0 0 0 0
0 0 0 0 0 0 0
2 2 2 2 2 2 1]
In B is what I would like to have, considering also overwrting (last row in B), and cases where there is only 1 value at the left of my 1 and not 4 as the fixed searching distance (second row).
How about this lovely one-liner?
n = 3;
const = 5;
A = [0 0 0 0 0 1 0;
0 1 0 0 0 0 0;
0 0 0 0 0 0 0;
0 0 0 0 1 0 1]
A(bsxfun(#ne,fliplr(filter(ones(1,1+n),1,fliplr(A),[],2)),A)) = const
results in:
A =
0 0 5 5 5 1 0
5 1 0 0 0 0 0
0 0 0 0 0 0 0
0 5 5 5 5 5 1
here some explanations:
Am = fliplr(A); %// mirrored input required
Bm = filter(ones(1,1+n),1,Am,[],2); %// moving average filter for 2nd dimension
B = fliplr(Bm); %// back mirrored
mask = bsxfun(#ne,B,A) %// mask for constants
A(mask) = const
Here is a simple solution you could have come up with:
w=4; % Window size
v=2; % Desired value
B = A;
for r=1:size(A,1) % Go over all rows
for c=2:size(A,2) % Go over all columns
if A(r,c)==1 % If we encounter a 1
B(r,max(1,c-w):c-1)=v; % Set the four spots before this point to your value (if possible)
end
end
end
d = 4; %// distance
v = 2; %// value
A = fliplr(A).'; %'// flip matrix, and transpose to work along rows.
ind = logical( cumsum(A) ...
- [ zeros(size(A,1)-d+2,size(A,2)); cumsum(A(1:end-d-1,:)) ] - A );
A(ind) = v;
A = fliplr(A.');
Result:
A =
0 2 2 2 2 1 0
2 1 0 0 0 0 0
0 0 0 0 0 0 0
2 2 2 2 2 2 1
Approach #1 One-liner using imdilate available with Image Processing Toolbox -
A(imdilate(A,[ones(1,4) zeros(1,4+1)])==1)=2
Explanation
Step #1: Create a morphological structuring element to be used with imdilate -
morph_strel = [ones(1,4) zeros(1,4+1)]
This basically represents a window extending n places to the left with ones and n places to the right including the origin with zeros.
Step #2: Use imdilate that will modify A such that we would have 1 at all four places to the left of each 1 in A -
imdilate_result = imdilate(A,morph_strel)
Step #3: Select all four indices for each 1 of A and set them to 2 -
A(imdilate_result==1)=2
Thus, one can write a general form for this approach as -
A(imdilate(A,[ones(1,window_length) zeros(1,window_length+1)])==1)=new_value
where window_length would be 4 and new_value would be 2 for the given data.
Approach #2 Using bsxfun-
%// Paramters
window_length = 4;
new_value = 2;
B = A' %//'
[r,c] = find(B)
extents = bsxfun(#plus,r,-window_length:-1)
valid_ind1 = extents>0
jump_factor = (c-1)*size(B,1)
extents_valid = extents.*valid_ind1
B(nonzeros(bsxfun(#plus,extents_valid,jump_factor).*valid_ind1))=new_value
B = B' %// B is the desired output
I have a dataset with about 20 million rows with the following format:
Userid attributid timeid
1 -1 0
1 -2 0
1 -3 0
1 -4 0
1 -5 0
...
and another index that match the attributeid to one of the four attribute type:
attributeid attributetype
-1 A
-2 B
-3 C
-4 D
-5 B
I would like to batch import the dataset into neo4j by converting it into the following format:
UserID A B C D timeid
1 -1 -2,-5 -3 -4 0
I tried R by order the dataframe using userid and scanning through it. But it was too slow. I was wondering what is the most time efficient way to do that? Or is there any thing I can do to optimize my code? Here is my code:
names(node_attri)[1] = 'UserID'
names(node_attri)[2] = 'AttriID'
names(node_attri)[3] = 'TimeID'
names(attri_type)[1] = 'AttriID'
names(attri_type)[2] = 'AttriType'
#attri_type <- attri_type[order(attri_type),]
#node_attri <- node_attri[order(node_attri),]
N = length(unique(node_attri$TimeID))*length(unique(node_attri$UserID))
new_nodes = data.frame(UserID=rep(NA,N), employer=rep(NA,N), major=rep(NA,N),
places_lived=rep(NA,N), school=rep(NA,N), TimeID=rep(NA,N))
row = 0
start = 1
end = 1
M =nrow(node_attri)
while(start <= M) {
row = row + 1
em = ''
ma = ''
pl = ''
sc = ''
while(node_attri[start,1] == node_attri[end,1]) {
if (attri_type[abs(node_attri[end,2]),2] == 'employer')
em = paste(em, node_attri[end,2], sep=',')
else if (attri_type[abs(node_attri[end,2]),2] == 'major')
ma = paste(ma, node_attri[end,2], sep=',')
else if (attri_type[abs(node_attri[end,2]),2] == 'places_lived')
pl = paste(pl, node_attri[end,2], sep=',')
else if (attri_type[abs(node_attri[end,2]),2] == 'school')
sc = paste(sc, node_attri[end,2], sep=',')
end = end + 1
if (end > M) break
}
new_nodes[row,] = list(UserID=node_attri[start,1], employer=substring(em,2),
major=substring(ma,2), places_lived=substring(pl,2),
school=substring(sc,2), TimeID=node_attri[start,3])
start = end
end = start
}
new_nodes = new_nodes[1:row,]
You need to merge, aggregate and then reshape. Assuming your dataframes are DFand DF2respectively:
x <- merge(DF, DF2)
y <- aggregate(attributeid~., data=x, FUN=function(x)paste(x, collapse=","))
z <- reshape(y, direction="wide", idvar=c("Userid","timeid"), timevar="attributetype")
Result:
> z
Userid timeid attributeid.A attributeid.B attributeid.C attributeid.D
1 1 0 -1 -5,-2 -3 -4
Renaming and rearranging columns is trivial.
Here is a solution using the reshape2 package and match.
library(reshape2)
##Create some sample data
dat1 <- data.frame(Userid=rep(1:4,each=5),attributeid=rep(-1:-5,4),timeid=rep(0:3,each=5))
index <- data.frame(attruibuteid=-1:-5,attributetype=c("A","B","C","D","B"))
##Merge the two using match
dat1$attributetype = index$attributetype[match(dat1$attributeid,index$attruibuteid)]
##Reformat using aggregate and dcast
dat2 <- aggregate(attributeid~attributetype+timeid+Userid,function(x){paste(x,collapse=",")},data=dat1)
dat3 <- dcast(formula=Userid+timeid~attributetype,value.var="attributeid",data=dat2)
> dat3
Userid timeid A B C D
1 1 0 -1 -2,-5 -3 -4
2 2 1 -1 -2,-5 -3 -4
3 3 2 -1 -2,-5 -3 -4
4 4 3 -1 -2,-5 -3 -4