我有一个MS访问查询,我在我的应用程序中运行,我能够使用SSMS运行查询(我知道这不是一个访问sql,但我可以使用它),当我导入它进入我的急剧应用程序我得到一个不正确的语法错误。 (我的c应用程序从访问dbf文件中读取)以下是完整的SQL:
SELECT ([T2_BRA].[REF] + [F7]) AS NewStyle,
Sum(T2_BRA.Q11) AS QTY1, Sum(T2_BRA.Q12) AS QTY2,
Sum(T2_BRA.Q13) AS QTY3, Sum(T2_BRA.Q14) AS QTY4, Sum(T2_BRA.Q15) AS QTY5, Sum(T2_BRA.Q16) AS QTY6, Sum(T2_BRA.Q17) AS QTY7, Sum(T2_BRA.Q18) AS QTY8,
Sum(T2_BRA.Q19) AS QTY9, Sum(T2_BRA.Q20) AS QTY10, Sum(T2_BRA.Q21) AS QTY11, Sum(T2_BRA.Q22) AS QTY12, Sum(T2_BRA.Q23) AS QTY13, T2_HEAD.REF,
Sum(T2_BRA.LY11) AS LY1, Sum(T2_BRA.LY12) AS LY2, Sum(T2_BRA.LY13) AS LY3, Sum(T2_BRA.LY14) AS LY4, Sum(T2_BRA.LY15) AS LY5,
Sum(T2_BRA.LY16) AS LY6, Sum(T2_BRA.LY17) AS LY7, Sum(T2_BRA.LY18) AS LY8, Sum(T2_BRA.LY19) AS LY9, Sum(T2_BRA.LY20) AS LY10,
Sum(T2_BRA.LY21) AS LY11, Sum(T2_BRA.LY22) AS LY12, Sum(T2_BRA.LY23) AS LY13, T2_BRA.BRANCH, T2_HEAD.LASTDELV, T2_EAN.EAN_CODE, T2_SIZES.S01 AS S1,
T2_SIZES.S02 AS S2,
T2_SIZES.S03 AS S3,
T2_SIZES.S04 AS S4,
T2_SIZES.S05 AS S5,
T2_SIZES.S06 AS S6,
T2_SIZES.S07 AS S7,
T2_SIZES.S08 AS S8,
T2_SIZES.S09 AS S9,
T2_SIZES.S10 AS S10,
T2_SIZES.S11 AS S11,
T2_SIZES.S12 AS S12,
T2_SIZES.S13 AS S13
FROM ((((((T2_BRA INNER JOIN T2_HEAD ON T2_BRA.REF = T2_HEAD.REF)) INNER JOIN T2_SIZES ON T2_HEAD.SIZERANGE = T2_SIZES.SIZERANGE) INNER JOIN
(SELECT Right(T2_LOOK.[KEY],3) AS NewCol, T2_LOOK.F1 AS MasterColour, Left(T2_LOOK.[KEY],3) AS Col, T2_LOOK.F7
FROM T2_LOOK
WHERE (Left(T2_LOOK.[KEY],3))='COL') as Colour ON T2_BRA.COLOUR = Colour.NewCol) LEFT JOIN T2_EAN ON T2_EAN.T2T_CODE LIKE (SELECT ('#' + ([T2_BRA].[REF] + [F7]) + '#'))))
WHERE [T2_BRA].[REF] = '010403' AND T2_BRA.BRANCH in ('A','G')
GROUP BY ([T2_BRA].[REF] + [F7]),T2_HEAD.REF, T2_BRA.BRANCH, T2_HEAD.LASTDELV, T2_EAN.EAN_CODE, T2_SIZES.S01,
T2_SIZES.S02, T2_SIZES.S03, T2_SIZES.S04, T2_SIZES.S05, T2_SIZES.S06, T2_SIZES.S07, T2_SIZES.S08, T2_SIZES.S09, T2_SIZES.S10, T2_SIZES.S11, T2_SIZES.S12, T2_SIZES.S13
我收到语法错误的行是:
LEFT JOIN T2_EAN ON T2_EAN.T2T_CODE LIKE (SELECT ('#' + ([T2_BRA].[REF] + [F7]) + '#')
任何帮助都会很棒! :)
答案 0 :(得分:1)
您的问题JOIN
子句存在MS Access方言的一些问题:
SELECT
必须包含FROM
来源; +
,而是&
运算符; LIKE
表达式可以在ON
子句中使用,但比较将逐行进行(不按可能的意图在连接表的所有行中搜索值)。 由于您尝试以LIKE
关系LEFT JOIN
表达式加入表格,因此上述纠正仍然存在挑战。
首先考虑用逗号分隔表 T2_EAN ,这等同于交叉连接,然后添加运行WHERE
子查询的EXISTS
子句。这样做,WHERE
成为隐式连接, T2_EAN 列将指向主查询中的字段。请注意,查询中的其他表必须使用INNER JOIN
来表示此逗号分隔的表。并删除LEFT JOIN
并调整括号。
FROM T2_EAN, (((((
...
WHERE [T2_BRA].[REF] = '010403' AND T2_BRA.BRANCH in ('A','G')
AND EXISTS
(SELECT 1 FROM [T2_BRA] t
WHERE T2_EAN.T2T_CODE LIKE ('%' & (t.[REF] & t.[F7]) & '%')
现在,这里的挑战是WHERE
将对应INNER JOIN
而非LEFT JOIN
。要解决此问题,请考虑添加与上面完全相同的UNION
(非UNION ALL
)查询,但不要使用EXISTS
子查询。然后,这将返回不符合LIKE
条件的记录,UNION
将遗漏重复项。见LEFT JOIN Equivalent here。请务必在引用 T2_EAN 列的地方向NULL
添加SELECT
:
SELECT ... T2_HEAD.LASTDELV, T2_EAN.EAN_CODE, T2_SIZES.S01 AS S1 ...
UNION
SELECT ... T2_HEAD.LASTDELV, NULL AS EAN_CODE, T2_SIZES.S01 AS S1 ...
请注意:此调整无法保证性能。进一步的考虑包括:
一旦查询编译并运行,请确保将此大型查询或视图保存为MS Access数据库中的存储对象,而不是脚本化的C#字符串查询。即使您没有MS Access GUI .exe,也可以使用MS Access'带有VBA的querydefs对象(即Excel VBA)或COM-interface with C#或支持COM的任何其他语言,如开源Python,PHP,R。
然后让C#app根据其目的检索视图:SELECT * FROM mySavedQuery
。由于Access引擎保存了最佳执行计划并缓存了统计信息,因此存储查询往往更有效,特别是对于许多连接和复杂查询而不是编码查询。
通过保存匹配值而不需要其他无关字符来删除LIKE
的需要,因此可以使用=
,因为我相信MS Access的LIKE
将不会使用索引在查询计划中。
将Access数据库升级到SQL Server,以便使用T-SQL方言进行更复杂的处理。 SQL Server在SSMS中具有轻松的功能,可以导入Access .mdb / .accdb文件。
答案 1 :(得分:0)
你LETER OUTER JOIN的ON
条款毫无意义:
LEFT JOIN T2_EAN ON T2_EAN.T2T_CODE LIKE (SELECT ('#' + ([T2_BRA].[REF] + [F7]) + '#')
您需要将T2_EAN
加入FROM子句中ALREADY PRESENT T2_BRA
表中的值。通过将T2_BRA
粘贴到子查询中,您将表格放入两次,这是无稽之谈。也不允许在LIKE
条件内使用子查询。
如果它被允许并且确实有意义,那么你最终会在这些内部连接和左外连接表的所有中间结果集之间得到一个笛卡尔积,这几乎绝对不是你所追求的。 / p>
相反(可能类似):
LEFT JOIN T2_EAN ON T2_EAN.T2T_CODE LIKE '#' + [T2_BRA].[REF] + [F7] + '#'
现在正在说“左外连接t2_ean
到T2_Bra
T2T_Code
匹配<any one digit> + T2_Bra.Ref + F7 + <any one digit>
的连接”在不知道您的数据的情况下,我无法保证这一点是你想要的东西,但在逆向工程你不正确的查询时,感觉就像是最接近的解释。
你在评论中提到“我尝试过使用所有通配符*,#和?”不要只是尝试使用通配符,希望有些东西可行。他们每个人都做了非常不同的事情。使用您需要的那种情况。 Decent explanation of the three wildcards that work with the LIKE
operator in access here。您可能希望在调试时切换到星号(因为它是通配符中最开放的星号),然后一旦获得合理的结果,请使用更紧密的#
(仅匹配一位数)运算符。